\ tag: forth interpreter
\ 
\ Copyright (C) 2003 Stefan Reinauer
\ 
\ See the file "COPYING" for further information about
\ the copyright and warranty status of this work.
\ 


\ 
\ 7.3.4.6 Display pause
\ 

0 value interactive?
0 value terminate?

: exit?
  interactive? 0= if
    false exit
  then
  false \ FIXME we should check whether to interrupt output
        \ and ask the user how to proceed.
  ;


\ 
\ 7.3.9.1 Defining words
\ 

: forget 
  s" This word is obsolescent." type cr
  ['] ' execute
  cell - dup 
  @ dup 
  last ! latest !
  here!
  ;
 
\ 
\ 7.3.9.2.4 Miscellaneous dictionary
\ 

\ interpreter. This word checks whether the interpreted word
\ is a word in dictionary or a number. It honours compile mode 
\ and immediate/compile-only words.

: interpret 
  0 >in !
  begin
    parse-word dup 0> \ was there a word at all?
  while
    $find 
    if
      dup flags? 0<> state @ 0= or if
        execute
      else
        ,             \ compile mode && !immediate
      then
    else              \ word is not known. maybe it's a number
      2dup $number
      if
        span @ >in !  \ if we encountered an error, don't continue parsing
        type 3a emit
	-13 throw
      else
        -rot 2drop 1 handle-lit
      then
    then
    depth 200 >=  if -3 throw then 
    depth 0<      if -4 throw then
    rdepth 200 >= if -5 throw then 
    rdepth 0<     if -6 throw then
  repeat
  2drop
  ;

: refill ( -- )
	ib #ib @ expect 0 >in ! ;

: print-status  ( exception -- )
  space
  ?dup if
    dup sys-debug \ system debug hook
    case 
       -1 of s" Aborted." type endof
       -2 of s" Aborted." type endof
       -3 of s" Stack Overflow." type 0 depth! endof
       -4 of s" Stack Underflow." type 0 depth! endof
       -5 of s" Return Stack Overflow." type endof
       -6 of s" Return Stack Underflow." type endof
      -13 of s" undefined word." type endof
      -15 of s" out of memory." type endof
      -21 of s" undefined method." type endof
      -22 of s" no such device." type endof
      dup s" Exception #" type . 
      0 state !
    endcase
  else
    state @ 0= if
      s" ok"
    else 
      s" compiled"
    then
    type
  then
  cr
  ;

defer status
['] noop ['] status (to)

: print-prompt
  status 
  depth . 3e emit space
  ;
  
defer outer-interpreter
:noname
  cr
  begin
    print-prompt
    source 0 fill           \ clean input buffer
    refill 

    ['] interpret catch print-status
    terminate?
  until
; ['] outer-interpreter (to)

\ 
\ 7.3.8.5 Other control flow commands
\ 

: save-source  ( -- )
  r>               \ fetch our caller
  ib >r #ib @ >r   \ save current input buffer
  source-id >r     \ and all variables 
  span @ >r        \ associated with it.
  >in @ >r
  >r               \ move back our caller
  ;

: restore-source ( -- )
  r> 
  r> >in ! 
  r> span ! 
  r> ['] source-id (to) 
  r> #ib ! 
  r> ['] ib (to) 
  >r
  ;

: (evaluate) ( str len -- ??? )
  save-source
  -1 ['] source-id (to)
  dup
  #ib ! span !
  ['] ib (to)
  interpret
  restore-source
  ; 

: evaluate ( str len -- ?? )
  2dup + -rot
  over + over do 
    i c@ 0a = if 
      i over - 
      (evaluate)
      i 1+ 
    then 
  loop 
  swap over - (evaluate)
  ;
  
: eval evaluate ;