I'm trying to wrap my head around the immediate and deferred execution. From what I understand is that the interpreter maintains a flag that knows if it in deferred execution or not.
Deferred execution of a procedure could be because a name lookup returned a procedure.
Now I'm trying to find 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 which returns an procedure. But this procedure is pushed, while it 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 there is a special rule:
Procedures appearing directly (either as part of a program being read from a file or as part of some larger procedure in memory) are usually part of a definition or of a construct, such as a conditional, that operates on the procedure explicitly. But procedures obtained indirectly—for example, as a result of looking up a name—are usually intended to be executed. A PostScript program can override these semantics when necessary.
I understand that if you encounter a procedure directly that you have to push it (even if it is executable). (The immediately evaluated name returns a procedure, which is encountered directly, so it should be pushed to the OS.)
Now if I'm thinking in code to implement this logic in an interpreter I can think of something like this:
If I have a literalname lookup, set the interpreter's DeferredFlag = true; Now how do I know when the deferred execution ends? I can hardcode if I encounter the "def" name, but there might be others.
(+ What in case procedures are nested in a procedure that is executing. etc...)
I can't find a way to control that DeferredFlag in the interpreter to know the current execution mode.
Hope the question is clear.
Update:
Some extra code samples I try to debug without success.
code 1:
/foo { 2 3 add } def
foo
% result: 5
code 2:
/foo { 2 3 add } def
//foo
% result: { 2 3 add }
code 3:
/foo { 2 3 add } def
/bar { foo } def
bar
% result: 5
code 4:
/foo { 2 3 add } def
/bar { //foo } def
bar
% result: { 2 3 add }