PostScript immediate or delayed execution

I try to bow my head to immediate and delayed execution. From what I understand, it is that the interpreter supports a flag that knows whether it is in deferred execution or not.

Delayed execution of a procedure may be caused by the fact that a name search returned a procedure.

Now I'm trying to figure out what types, actions, or operations control this interpreter flag.

For example, this piece of code below has an immediately evaluated name at the end that returns the procedure. But this procedure is pushed, and it is executable (xcheck):

/setdata
{
  /a 1 def
  /b 0 def

 /foo
   a 0 ne
   b 0 ne
   and
 def

 { foo false and }
} def

//setdata

I know that there is a special rule:

, ( ) , , . - , - . PostScript .

, , ( ). ( , , .)

, , - :

, DeferredFlag = true; , , ? hardcode, "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 }
+4
1

. . , , , , . DeferredFlag.

, : token.

token " ", . , , token .

{ execution is deferred until the closing }

, postscript, , , , .. . , 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 . , . " ".

Edit:

. op_stack . - , token. , token // s.

$ 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>
+3

Source: https://habr.com/ru/post/1678321/


All Articles