Next: , Previous: Attributes, Up: R Internal Structures



1.4 上下文

上下文(Contexts)是用于跟踪一个计算从哪里开始或 去向的内部机制,因此控制流可以工作,在程序执行发生错误 时可以获得相关信息(如通过回溯的办法), 以及其它一些特定用途(比如函数 sys.xxx)。

程序的执行上下文(Execution context)是 C structs的堆栈:

     typedef struct RCNTXT {
         struct RCNTXT *nextcontext; /* 链表中的上一个上下文 */
         int callflag;               /* 上下文 `类型' */
         JMP_BUF cjmpbuf;            /* C 堆栈和寄存器信息 */
         int cstacktop;              /* 指针保护堆栈的顶部 */
         int evaldepth;              /* 初始的求值深度(Evaluation depth) */
         SEXP promargs;              /* 用于闭包(closure)的允诺(Promises) */
         SEXP callfun;               /* 被调用的闭包 */
         SEXP sysparent;             /* 调用闭包的环境 */
         SEXP call;                  /* 影响该上下文的调用 */
         SEXP cloenv;                /* 当前环境 */
         SEXP conexit;               /* 被解释过的 on.exit 代码 */
         void (*cend)(void *);       /* C on.exit thunk 程序 */
         void *cenddata;             /* C on.exit thunk 程序的数据 */
         char *vmax;                 /* R_alloc 堆栈的顶部 */
         int intsusp;                /* 暂停中断 */
         SEXP handlerstack;          /* 条件处理器堆栈 */
         SEXP restartstack;          /* 可用的重启动的堆栈 */
     } RCNTXT, *context;

在未来的字节码编译器里面,还会加上其它的字段。 `类型'(types)主要来自

     enum {
         CTXT_TOPLEVEL = 0,  /* 顶层的上下文 */
         CTXT_NEXT     = 1,  /* next对应的目标 */
         CTXT_BREAK    = 2,  /* break对应的目标 */
         CTXT_LOOP     = 3,  /* breaknext 对应的目标 */
         CTXT_FUNCTION = 4,  /* 函数闭包 */
         CTXT_CCODE    = 8,  /* 其它需要错误清理的函数 */
         CTXT_RETURN   = 12, /* 从一个闭包中返回(return() */
         CTXT_BROWSER  = 16, /* 从浏览器中返回对象 */
         CTXT_GENERIC  = 20, /* 运行S3方法 */
         CTXT_RESTART  = 32, /* 调用闭包产生的 restart */
         CTXT_BUILTIN  = 64  /* 内置函数 */
     };

其中 CTXT_FUNCTION 二进制位在 涉及到函数闭包时打开。

上下文通过调用begincontext创建,而调用 endcontext来关闭:代码可以通过findcontext 来查找上下文的一些特别类型(而且跳到那里)或者 通过R_JumpToContext跳到一个特定的上下文。 R_ToplevelContext 是一种`空闲'的状态(通常是命令提示符), 而 R_GlobalContext 在堆栈的顶部。

注意,所有闭包调用时都会设置一个上下文,但调用内部函数的时候从来 都不会,而调用内置的内部函数这样做只是最近的事情( 之前,只在指令剖析的时候发生)。

通过S3泛型定义(通过 UseMethod 或它的内置等价函数)或调用 NextMethod的方法分发会把上下文类型设置为CTXT_GENERIC。 这用于设置方法调用和genericsysparent。 这样使得方法看上去被直接调用而不是通过泛型调用 1

R 命令 sys.framesys.call通过对 上下文堆栈的任一末端的闭包的调用的计数来工作。

注意,结构的sysparent 元素和sys.parent()不是同一个东西。 元素 sysparent 主要用于管理被求值的函数,也就是通过 调用 Recall 和方法分发。

现在,CTXT_CCODE 上下文用于 cat()load()scan()write.table()(在错误中关闭连接) 中。 它通过 PROTECT,序列化(serialization)(从 错误中恢复,例如:释放缓冲)和放置在错误处理代码(提高 C堆栈的限制和重新设置一些变量)。


Footnotes

[1] 原文为:This is used to set the sysparent of the method call to that of the generic, so the method appears to have been called in place of the generic rather than from the generic.