M[UMPS] Commands

D[O]

Introduced in the 1977 ANSI M[UMPS] language standard.

DO LABEL

DO LABEL+OFFSET
Note that use of the LABEL+OFFSET syntax may have unintended ramifications when lines of code are inserted between the line with the LABEL and the line that was indicated by LINE+OFFSET before the insertion.

DO ^PROGRAM

DO LABEL^PROGRAM

DO LABEL+OFFSET^PROGRAM

DO @ARGUMENT

DO @INDLABEL^PROGRAM

DO @INDLABEL^@INDPROG

Note: a reference like +OFFSET^ROUTINE is acceptable as a parameter for $TEXT, but not as an argument for the commands DO and GOTO.

The 1990 M[UMPS] language standard added:

DO LABEL(actuallist)

DO @INDLABEL(actuallist)

DO @X(A)
Does not do parameter passing. Uses indirect array element.

DO @X(.A)
Does parameter passing.

DO @X(B)(A)
Does routine indirect X(B) passing the value of A.

DO @X^@Y
Does label @X in routine @Y.

DO @X^@Y(A)
Does label @X in routine @Y(A).

DO @X^@Y(.A)
Does label @X in routine @Y passing A by reference.

DO @X^@Y(B)(A)
Does label @X in routine @Y(B) passing the value of A.

An offset is an integer expression. This means that the following three invocations all address the same entry point:
DO A+1^B
DO A+1.5^B
DO A+1.9999999999^B

Assume that the following label exists
SUB(A,B) ;

The subroutine call DO SUB(12) will have the result that, within the subroutine, the formal parameter B will initially be undefined (i.e. $DATA(B) = 0).

The subroutine call DO SUB(1,2,43) will cause an error, because there is no matching formal parameter for the actual parameter 43.

Assume that a M[UMPS] routine contains the command

DO ^EXAMPLE(1)

and that routine EXAMPLE looks like
FIRST ; author ; date/time ; function
EXAMPLE(X) ;
 WRITE !,X
 QUIT

The DO command will cause an error (M20) when the (sub)routine is called and control is transferred to the first line. Because an actual parameter is specified, that first line (regardless of what the actual label is on that line) should have a formal parameter list. The absence of a parameter list on the line to which control is transferred will cause the error condition.

Assume that a M[UMPS] routine contains the command

DO ^EXAMPLE(1)

and that routine EXAMPLE looks like
FIRST(X) ; author ; date/time ; function
 ;
 WRITE !,X
 QUIT

The DO command will cause the value 1 to be displayed. Regardless of the actual label on the first line, the parameter is passed through the parameter list on the first line of the routine.

 SET VA=1 DO
 . DO SUB
 . QUIT
 WRITE VA
 QUIT
 ;
SUB SET VA=2
 QUIT

The value 2 will be written. While the command DO SUB occurs at a line with level 2, the DO command invokes a new block of code, which happens to start at level 1; there is no implicit QUIT command because the line at label SUB is of a lower level than the line containing the DO command. Within an 'indented block', subroutines may be called, even if they reside in other routines.

 SET EXP2=0
 IF EXP1 DO
 . WRITE !,"First: ",$TEST
 . IF EXP2
 . WRITE !,"Second: ",$TEST
 . WRITE !,"Today is ",$$DAY,"."
 . QUIT
 WRITE !,"Third: ",$TEST
 QUIT
 ;
DAY() NEW DAYS
 SET DAYS="Thurs Fri Satur Sun Mon Tues Wednes"
 QUIT $PIECE(DAYS," ",$HOROLOG#7+1)_"day"

If local variable EXP1 is false, this example will write:
Third: 0
If local variable EXP1 is true, this example will write:
First: 1
Second: 0
Today is xxxxxday.
Third: 1

The value of $TEST is stacked within the argumentless DO command, and reset to its original value when control returns back from the indented block to the next higher level.

 SET A="President"
 DO SUB1(.A)
 WRITE !,A
 QUIT
 ;
SUB1(B) KILL B
 SET B="Prime minister"
 QUIT

Local variable A is passed by reference to subroutine SUB1. Even though the value of the variable is removed by means of the KILL command, the 'by reference' link remains in effect. Thus, when the value "Prime minister" is assigned to parameter variable B, it is actually assigned to local variable A, which means that the value "Prime minister" will be written.

 SET SUM=$$ADD(A,A)
 SET WHICH=$$WHICH(12,34)
 QUIT
ADD(P,Q) QUIT P+Q
WHICH(Z,Z) WRITE Z
 SET RESULT=Z  QUIT RESULT

While it makes perfect sense to pass the same value multiple times as an actual parameter, it is considered to be erroneous to have multiple formal parameters with the same name.

While the 1990 ANSI M[UMPS] language standard does not specify any behavior in such a case, the 1995 ANSI M[UMPS] language standard specifies that multiple occurrences of the same name in a formal parameter list is an error.

If an implementation does not return an error (pre-1995 implementation), it is to be expected that the value 34 (because the parameterlist is scanned left-to-right, the rightmost occurrence of the name wins) will be written.

 SET Y="President"
 DO WHICH(.Y,"Court Jester")
 WRITE !,Y
 QUIT
 ;
WHICH(Z,Z) WRITE !,Z
 QUIT

In this example, the above mentioned phenomenon is taken one step further. Although this usage is considered to be erroneous (and post-1995 implementations will produce an error), pre-1995 implementations may allow such usage.

Within the subroutine 'the rightmost occurrence of the name wins', and the value "Court Jester" will be displayed. However, this is only because of the link between the parameter variable and the values passed.
The original local variable Y is not changed in any way, and the main routine will display the value "President".

ELECTION SET X="Mr. Sun"
 DO VOTE(.X)
 WRITE X
 QUIT
VOTE(Y) SET Y="Mr. Moon"
 QUIT

The value "Mr. Moon" will be written. Local variable X is passed by reference to the subroutine VOTE, and all changes that are made to parameter variable Y will be visible in the local variable to which it is bound 'by reference'.

Upon return from a subroutine or function, the "NEWed" variables are reset to their original state. If such a state was "undefined", then the variable in question will no longer have any value that was assigned within a subroutine or procedure.

KILL
SET A=1,B=2 DO SUB(B,.C,D)
WRITE $DATA(A),", ",$DATA(B),", ",$DATA(C),", " WRITE $DATA(D),", ",$DATA(E),", ",$DATA(F)
WRITE !,"B=",B,", D=",D
QUIT
SUB(A,C,F) SET A=3,B=5,C=7,D=9,F=11
QUIT

will produce:

1, 1, 1, 1, 0, 0
B=5, D=9

Note that local variable C is passed by reference, so the assignment within the subroutine is still visible after the QUIT from the subroutine, and local variable D is passed by reference, so the assignment F=11 is to a local copy within the subroutine, which disappears when the QUIT command is executed, and the assignment D=9 is to the original variable, so that this assignment will be persistent after the subroutine has completed.

Assume that a routine contains the command:
DO A+$$B^C
One might wonder how to interpret this address. Seemingly, there are two possible interpretations:


Because of the way that the "offset" is defined, the "longest" sequence of characters that fits the syntax of an integer expression is used to calculate the offset, i.e. the second interpretation is the one supported by the language standard.

The behavior of $TEST is different when the DO command does not have an argument:

IF A=B DO ONE
ELSE  DO TWO

In this example, the code following the ELSE command will be executed:

IF A=B DO
 . DO ONE
 . QUIT
ELSE  DO
 . DO TWO
 . QUIT

In this example, the code following the ELSE command will only be executed when A happens to be unequal to B. Any changes to the value of $TEST that may happen inside subroutine ONE are "undone" when control reverts to the level where the argument-less DO command was executed.

Addition in the 1995 ANSI M[UMPS] language standard:

Parameters may be omitted:
Assume that the following label occurs:
LABEL(P,Q,R,S,T,U) ; Entry in ROUTINE

Most commonly, the subroutine would be invoked using a reference like: DO LABEL^ROUTINE(A,B,C,D,E,F)

According to the 1990 ANSI M[UMPS] language standard, trailing parameters may be omitted:
DO LABEL^ROUTINE(A,B)
causes that within the subroutine: $DATA(R)=0, $DATA(S)=0, $DATA(T)=0 and $DATA(U)=0

The addition is that any parameter may be omitted:
DO LABEL^ROUTINE(A,B,,D,E,.F)
causes that within the subroutine: $DATA(R)=0, $DATA(S)=1, $DATA(T)=1 and $DATA(U)=$DATA(F)

Approved for addition in a future ANSI M[UMPS] language standard:

The special variable $TEST may occur as an argument of the NEW command.

 SET T="$TEST should be "
 IF REASON DO SUB1 WRITE !,T,"1: ",$TEST,"."
 ELSE  DO SUB2 WRITE !,T,"1: ",$TEST,"."
 QUIT
SUB1 WRITE !,T,"1: ",$TEST,"."
 NEW $TEST
 IF 0 ; Force $TEST to a new value
 QUIT
SUB2 WRITE !,T,"0: ",$TEST,"."
 IF 1 ; Force $TEST to a new value
 QUIT

Examples with naked references:

DO ROUTINE
SET ^ABC(1,2)="reset naked indicator"
; Naked indicator is now ^ABC(1,
DO @^(3,4)
; Naked indicator is now: ^ABC(1,3,
; Actual reference is: ^ABC(1,3,4)

DO ROUTINE(PARAMETERS)
SET ^ABC(1,2)="reset naked indicator"
; Naked indicator is now ^ABC(1,
DO ^routine(^(3,4),^(5,6))

; 1. fetch ^(3,4) = ^ABC(1,3,4)
; 2. fetch ^(5,6) = ^ABC(1,3,5,6)
; Naked indicator is now: ^ABC(1,3,5,


This document is © Ed de Moel, 1995-2005.
It is part of a book by Ed de Moel that is published under the title "M[UMPS] by Example" (ISBN 0-918118-42-5).
Printed copies of the book are no longer available.

This document describes the various commands that are defined in the M[UMPS] language standard (ANSI X11.1, ISO 11756).

The information in this document is NOT authoritative and subject to be modified at any moment.
Please consult the appropriate (draft) language standard for an authoritative definition.

In this document, information is included that will appear in future standards.
The MDC cannot guarantee that these 'next' standards will indeed appear.