% Unlambda interpreter

% usage:
%    gs -q -sDEVICE=nullpage unl.ps
% or
%    gs -q -sDEVICE=nullpage -- unl.ps filename

/evaluate {[ {done} 3 -1 roll ev} bind def

/done {exch pop} bind def

/ev {
    dup 0 get /a eq
     {aload pop 3 -1 roll pop {ev1} 3 -1 roll ev}
     {exch exec}
    ifelse
} bind def

/ev1 {
    dup 0 get /d eq
     {pop [ /d1 3 -1 roll ] exch exec}
     {{ap} 3 -1 roll ev}
    ifelse
} bind def

/ap {exch dup 0 get cvx exec} bind def

/k {pop [ /k1 3 -1 roll ] exch exec} bind def
/k1 {1 get 3 1 roll pop exec} bind def
/s {pop [ /s1 3 -1 roll ] exch exec} bind def
/s1 {1 get exch [ /s2 4 2 roll ] exch exec} bind def
/s2 {dup 1 get 2 index [ /a 4 2 roll ] 3 1 roll 2 get exch
     [ /a 4 2 roll ] [ /a 4 2 roll ] ev} bind def
/i {pop exch exec} bind def
/v {3 1 roll pop exec} bind def
/e {pop /tmp exch def ] pop tmp} bind def
/d1 {1 get exch [ /a 4 2 roll ] ev} bind def
/c1 {1 get /tmp exch def /tmp2 exch def ] pop [ tmp aload pop tmp2 exch exec}
    bind def
/c {pop /tmp exch def ]
     [ exch aload [ /c1 3 -1 roll ] [ /a tmp 4 -1 roll ] ev} bind def
/dot {1 get print exch exec} bind def
/ats {pop [ stdin 1 string readstring exch /curch exch def {/i} {/v} ifelse ]
     [ /a 4 2 roll ] ev} bind def
/que {1 get curch eq {/i} {/v} ifelse [exch] [ /a 4 2 roll ] ev} bind def
/pip {pop [ curch dup () eq {pop /v} {/dot exch} ifelse ]
      [ /a 4 2 roll ] ev} bind def
/sla {pop [ curch dup () eq {pop /v} {/que exch} ifelse ]
      [ /a 4 2 roll ] ev} bind def

/flushline {
    { dup 1 string readstring not dup {exch pop exit} if
      exch (\n) eq {exit} {pop} ifelse} loop exch pop } bind def
      
/nexttok {
    { src 1 string readstring not {error} if
      dup (#) eq {pop src flushline {error} if }
      { dup dup ( ) ne exch (\n) ne and {exit} {pop} ifelse }
      ifelse } loop } bind def

/parse {
      [ nexttok
      dup (`) eq { pop /a parse parse }
      { dup (.) eq { pop /dot src 1 string readstring not {error}}
        { dup (?) eq { pop /que src 1 string readstring not {error}}
	  { dup (@) eq {pop /ats}
	    { dup (|) eq {pop /pip}
	      { dup (/) eq {pop /sla}
	        { dup (r) eq {pop /dot (\n)}
	          {cvn} ifelse
		} ifelse
	      } ifelse
	    } ifelse
	  } ifelse
	} ifelse
      } ifelse
      ] } bind def

/stdin (%stdin) (r) file def
currentdict /ARGUMENTS known {ARGUMENTS length 0 eq} {true} ifelse
{ /src stdin def parse stdin flushline pop }
{ /src ARGUMENTS 0 get (r) file def parse src closefile } ifelse
/curch () def
evaluate
quit