文章目录
-
第三章 Caché 变量大全 $ESTACK 变量 - 大纲
- 描述
- 示例
- 注意
- `$ESTACK`和错误处理
包含从用户定义的点保存在调用堆栈上的上下文帧的数量。
大纲$ESTACK
$ES
描述
$ESTACK
包含从用户定义的点为JOB
保存在调用堆栈上的上下文帧的数量。可以通过使用new
命令创建$ESTACK
的新副本来指定这一点。
$ESTACK
特殊变量类似于$STACK
特殊变量。两者都包含当前保存在JOB
或程序的调用堆栈中的上下文框架的数量。更改上下文时,Caché会递增并恢复两者。主要区别在于,可以随时使用NEW
命令将$ESTACK
计数重置为零。无法重置$STACK
计数。
上下文框架和调用堆栈
启动Caché映像时,在将任何上下文保存到调用堆栈之前,$ESTACK
和$STACK
的值均为零。每次例程使用DO
调用另一个例程时,系统都会将当前正在执行的例程的上下文保存在调用堆栈中,递增$ESTACK
和$STACK
,并在新创建的上下文中开始执行被调用例程。被调用的例程可以依次调用另一个例程,依此类推。每次调用另一个例程时,Caché都会递增$ESTACK
和$STACK
并将更多保存的上下文放在调用堆栈中。
发出DO
命令,EXECUTE
命令或对用户定义函数的调用会建立新的执行上下文。不会发出GOTO
命令。
当DO
命令,XECUTE
命令或用户定义的函数引用创建新上下文时,Caché将增加$STACK
和$ESTACK
的值。当QUIT
命令导致上下文退出时,Caché从调用堆栈中恢复以前的上下文,并减小$STACK
和$ESTACK
的值。
不能使用SET
命令修改$ESTACK
和$STACK
特殊变量。尝试这样做会导致<SYNTAX>
错误。
创建$ESTACK
可以使用NEW
命令在任何上下文中创建$ESTACK的新副本。 Caché采取以下行动:
- 保存
$ESTACK
的旧副本。 - 创建新的
$ESTACK
副本,其值为零(0)。
这样,可以将特定上下文建立为$ESTACK
级别0上下文。当使用DO
,XECUTE
或用户定义的函数创建新的上下文时,Caché会将此$ESTACK
值递增。但是,当退出创建新$ESTACK
的上下文时($ESTACK
处于级别0),Caché会还原$ESTACK
的先前副本的值。
以下示例显示了$ESTACK
上的NEW命令的作用。在此的示例MainRoutine
显示$STACK
和$ESTACK
的初始值(它们是相同的值)。然后,它调用Sub1。该调用将增加$STACK
和$ESTACK
。 NEW
命令创建一个值为0的$ESTACK
。Sub1
调用Sub2
,递增$STACK
和$ESTACK
。返回MainRoutine
将恢复$STACK
和$ESTACK
的初始值:
/// d ##class(PHA.TEST.SpecialVariables).ESTACK()
ClassMethod ESTACK()
{
Main
WRITE !,"Initial: $STACK=",$STACK," $ESTACK=",$ESTACK
DO Sub1
WRITE !,"Return: $STACK=",$STACK," $ESTACK=",$ESTACK
QUIT
Sub1
WRITE !,"Sub1Call: $STACK=",$STACK," $ESTACK=",$ESTACK
NEW $ESTACK
WRITE !,"Sub1NEW: $STACK=",$STACK," $ESTACK=",$ESTACK
DO Sub2
QUIT
Sub2
WRITE !,"Sub2Call: $STACK=",$STACK," $ESTACK=",$ESTACK
QUIT
}
DHC-APP>d ##class(PHA.TEST.SpecialVariables).ESTACK()
Initial: $STACK=1 $ESTACK=1
Sub1Call: $STACK=2 $ESTACK=2
Sub1NEW: $STACK=2 $ESTACK=0
Sub2Call: $STACK=3 $ESTACK=1
Return: $STACK=1 $ESTACK=1
下面的示例演示了如何通过发出DO
和XECUTE
命令在创建新上下文时增加$ESTACK
的值,并在退出这些上下文时减小其值。它还显示GOTO
命令不会创建新上下文或增加$ESTACK
:
/// d ##class(PHA.TEST.SpecialVariables).ESTACK1()
ClassMethod ESTACK1()
{
Main
NEW $ESTACK
WRITE !,"Initial Main: $ESTACK=",$ESTACK // 0
DO Sub1
WRITE !,"Return Main: $ESTACK=",$ESTACK // 0
QUIT
Sub1
WRITE !,"Sub1 via DO: $ESTACK=",$ESTACK // 1
XECUTE "WRITE !,""Sub1 XECUTE: $ESTACK="",$ESTACK" // 2
WRITE !,"Sub1 post-XECUTE: $ESTACK=",$ESTACK // 1
GOTO Sub2
Sub1Return
WRITE !,"Sub1 after GOTO: $ESTACK=",$ESTACK // 1
QUIT
Sub2
WRITE !,"Sub2 via GOTO: $ESTACK=",$ESTACK // 1
GOTO Sub1Return
}
DHC-APP>d ##class(PHA.TEST.SpecialVariables).ESTACK1()
Initial Main: $ESTACK=0
Sub1 via DO: $ESTACK=1
Sub1 XECUTE: $ESTACK=2
Sub1 post-XECUTE: $ESTACK=1
Sub2 via GOTO: $ESTACK=1
Sub1 after GOTO: $ESTACK=1
Return Main: $ESTACK=0
注意
终端提示的上下文级别
从程序调用的例程与在终端提示下使用DO
命令调用的例程在不同的上下文级别开始。在终端提示下输入DO
命令时,系统会为该例程创建一个新的上下文。
调用的例程可以通过建立$ESTACK Level 0
上下文进行补偿,然后对所有上下文级引用使用$ESTACK
。
请考虑以下例程:
/// d ##class(PHA.TEST.SpecialVariables).ESTACK2()
ClassMethod ESTACK2()
{
START
; 建立$ESTACK 0级上下文
NEW $ESTACK
; 显示$STACK上下文级别
WRITE !,"$STACK level in routine START is ",$STACK
; 显示$ESTACK上下文级别并退出
WRITE !,"$ESTACK level in routine START is ",$ESTACK
QUIT
}
从程序运行Start
时,会看到以下显示:
$STACK level in routine START is 0
$ESTACK level in routine START is 0
当在终端提示符下发出do^start
命令来运行START
时,会看到以下显示:
DHC-APP>d ##class(PHA.TEST.SpecialVariables).ESTACK2()
$STACK level in routine START is 1
$ESTACK level in routine START is 0
$ESTACK
和错误处理
当错误处理程序必须将调用堆栈展开到特定上下文级别时,$ESTACK
在错误处理期间特别有用。