首页 文章

PostScript立即执行或延迟执行

提问于
浏览
4

我试图围绕即时和延期执行 . 据我所知,解释器维护一个标志,知道它是否在延迟执行中 .

延迟执行过程可能是因为名称查找返回了一个过程 .

现在我试图找出控制此解释器标志的类型,操作或操作 .

例如,下面的这段代码在结尾处有一个立即计算的名称,它返回一个过程 . 但是这个程序被推送了,而它是可执行的(xcheck):

/setdata
{
  /a 1 def
  /b 0 def

 /foo
   a 0 ne
   b 0 ne
   and
 def

 { foo false and }
} def

//setdata

我知道有一个特殊规则:

直接出现的程序(作为从文件读取的程序的一部分或作为内存中某个较大过程的一部分)通常是定义或构造的一部分,例如条件,它明确地对过程进行操作 . 但间接获得的程序 - 例如,由于查找名称 - 通常是为了执行 . PostScript程序可以在必要时覆盖这些语义 .

我明白,如果你直接遇到一个程序,你必须推它(即使它是可执行的) . (立即计算的名称返回一个直接遇到的过程,因此应将其推送到操作系统 . )

现在如果我在编写代码来在解释器中实现这个逻辑,我可以想到这样的事情:

如果我有文字名查找,请设置解释器的DeferredFlag = true;现在我怎么知道延迟执行何时结束?如果我遇到“def”名称,我可以进行硬编码,但可能还有其他名称 .

(如果程序嵌套在正在执行的过程中,等等...)

我找不到一种方法来控制解释器中的DeferredFlag以了解当前的执行模式 .

希望问题很清楚 .

Update:

我尝试调试一些额外的代码示例但没有成功 .

代码1:

/foo { 2 3 add } def
foo
% result: 5

代码2:

/foo { 2 3 add } def
//foo
% result: { 2 3 add }

代码3:

/foo { 2 3 add } def
/bar { foo } def
bar
% result: 5

代码4:

/foo { 2 3 add } def
/bar { //foo } def
bar
% result: { 2 3 add }

1 回答

  • 3

    在尝试理解翻译时,我遇到了许多相同的问题和困惑 . IMO术语延迟执行并不是很有用 . 另外,我认为立即评估的术语也不是很有用 . 您不需要DeferredFlag .

    这里涉及两个独立但相关的部分:解释器循环和 token 运算符 .

    token 处理"deferred execution"的一部分,它将可执行数组的所有标记收集到一个对象中 . 因此,如果文件或字符串以过程体开头,则在其上调用 token 将产生整个过程体 .

    { execution is deferred until the closing }
    

    它看起来像一个注释,但这是一行postcript代码,即使没有定义延迟,结束等单词,它也会毫无错误地运行 . 但是,如果你在它上面调用 exec ,或者将它定义为一个名称,那么它将执行,最好定义内容 .

    解释器循环总是从exec堆栈中抓取顶层对象,并且在语义上,可执行数组,文件和字符串的行为都相同 . 解释器将其视为源并获取第一个元素 . 名称案例略有不同,因为它本身并不是一个来源 . (我正在介绍我自己的这个概念,希望它能帮助/工作 . )在C-ish伪代码中:

    main_loop(){
        while( ! quit ){
            eval();
        }
    }
    
    eval(){
        object = pop( exec_stack );
        if( !executable_flag( object ) )  push( op_stack, object );
        else switch( type_of( object ) ){
            case array: array_handler( object ); break;
            case string: string_handler( object ); break;
            case file: file_handler( object ); break;
            case name: name_handler( object ); break;
            default: push( op_stack, object );
        }
    }
    

    在名称的情况下,查找名称并执行可执行文件 .

    name_handler( object ) {
        object = load( object );
        push( executable_flag( object ) ? exec_stack : op_stack, object );
    }
    

    在其他三个中,您还必须检查它是否是一个数组 .

    array_handler( object ){
        switch( length( object ){
        default:
            push( exec_stack, getinterval( object, 1, length( object ) - 1 ) );
            /* fall-thru */
        case 1:
            object = get( object, 0 );
            push( executable_flag( object ) && type_of( object ) != array ?
                  exec_stack : op_stack, object );
        case 0:
            /* do nothing */
        }
    
    }
    

    只有当 executable_flag( object ) && type_of( object ) != array 然后你推到exec堆栈 .

    对于另一个问题,立即评估的名称,我更喜欢称它们为立即加载的名称 . token 运算符在返回之前调用 load . 如果在正确的地方完成,易于处理 . 它与"deferred-execution"部分没有真正的互动 .

    编辑:

    我通过追踪来运行你的样本debugger . 这显示了每个令牌执行后op_stack的运行图 . 左边的元素是 token 返回的对象 . 请注意 token 已经消耗了所有 // .

    $ cat test.ps
    (db5.ps) run currentfile cvx traceon debug
    
    /foo { 2 3 add } def
    foo
    % result: 5
    
    /foo { 2 3 add } def
    //foo
    % result: { 2 3 add }
    
    /foo { 2 3 add } def
    /bar { foo } def
    bar
    % result: 5
    
    /foo { 2 3 add } def
    /bar { //foo } def
    bar
    % result: { 2 3 add }
    
    $ gsnd -DNOSAFER test.ps
    GPL Ghostscript 9.19 (2016-03-23)
    Copyright (C) 2016 Artifex Software, Inc.  All rights reserved.
    This software comes with NO WARRANTY: see the file PUBLIC for details.
     %|- 
    /foo  %|- /foo 
    {2 3 add}  %|- /foo {2 3 add} 
    def  %|- 
    foo  %|- 5 
    /foo  %|- 5 /foo 
    {2 3 add}  %|- 5 /foo {2 3 add} 
    def  %|- 5 
    {2 3 add}  %|- 5 {2 3 add} 
    /foo  %|- 5 {2 3 add} /foo 
    {2 3 add}  %|- 5 {2 3 add} /foo {2 3 add} 
    def  %|- 5 {2 3 add} 
    /bar  %|- 5 {2 3 add} /bar 
    {foo}  %|- 5 {2 3 add} /bar {foo} 
    def  %|- 5 {2 3 add} 
    bar  %|- 5 {2 3 add} 5 
    /foo  %|- 5 {2 3 add} 5 /foo 
    {2 3 add}  %|- 5 {2 3 add} 5 /foo {2 3 add} 
    def  %|- 5 {2 3 add} 5 
    /bar  %|- 5 {2 3 add} 5 /bar 
    {{2 3 add}}  %|- 5 {2 3 add} 5 /bar {{2 3 add}} 
    def  %|- 5 {2 3 add} 5 
    bar GS<4>
    GS<4>pstack
    {2 3 add}
    5
    {2 3 add}
    5
    GS<4>
    

相关问题