;;; This compiles up "fib-loop", the bytecode version
;;; of fibonocci used to generate the times reported
;;; in TIMES.
;;;

(begin
  (define fib-loop-code
    '(
      (decl x   	(ilocal 0))
      (decl loop-count	(ilocal 1))
      (decl tn-2	(ilocal 2))
      (decl tn-1	(ilocal 3))
      (decl tn		(ilocal 4))
      (decl saved-x	(ilocal 5))

      (load	x)
      (store	saved-x)
      (iinc	saved-x -2)


      main-loop
      (load	0)
      (load	loop-count)
      (if_icmpge break)
      (iinc	loop-count -1)

      (load 	1)
      (store 	tn-2)

      (load 	1)
      (store 	tn-1)

      (load	saved-x)
      (store	x)

      fib-loop_loop

      (load	0)
      (load	x)
      (if_icmpge main-loop)
      
      (load	tn-2)
      (load	tn-1)
      (iadd)
      (store	tn)

      (load	tn-1)
      (store	tn-2)

      (load	tn)
      (store	tn-1)

      (iinc	x -1)
      (goto 	fib-loop_loop)

      break
      (load	tn-1)
      (ireturn)))

  (define fib-loop-bytes (string->symbol (li-assemble fib-loop-code #f #f)))
  (define fib-loop (intern-bytecode (make-vector 1 #f) 'fib-loop '#{(i)i}# 10 10 fib-loop-bytes)))




;;; The file c2.scm contains a compiler back-end for
;;; a c-like language called ctax.  Here is fib
;;; in ctax:
;;;
;;;	int
;;;	fib (int x)
;;;     {
;;;        int tn, tn1, tn2;
;;;	   tn = tn1 = tn2 = 1;
;;;        for (x = x - 2; x; x = x - 1)
;;;	     {
;;;	       tn = tn1 + tn2;
;;;            tn2 = tn1;
;;;            tn1 = tn;
;;;          }
;;;        return tn;
;;;      }


;;; Here is the code currently emitted by the bytecode
;;; compiler for a syntax tree for the ctax version
;;; of fib.  As you can see, the compiler has yet to
;;; learn to use the iinc instruction, but is otherwise
;;; reasonable:
;;;

;;; (#(())
;;;  fib
;;;  "(i)i"
;;;  4
;;;  2
;;;  ((decl tn (ilocal 3))
;;;   (decl tn1 (ilocal 2))
;;;   (decl tn2 (ilocal 1))
;;;   (decl x (ilocal 0))
;;;   (load 1)
;;;   (dup)
;;;   (store tn)
;;;   (dup)
;;;   (store tn1)
;;;   (store tn2)
;;;   (load x)
;;;   (load 2)
;;;   (isub)
;;;   (store x)
;;;   for3
;;;   (load x)
;;;   (ifeq break5)
;;;   (load tn2)
;;;   (load tn1)
;;;   (iadd)
;;;   (store tn)
;;;   (load tn1)
;;;   (store tn2)
;;;   (load tn)
;;;   (store tn1)
;;;   continue-label4
;;;   (load x)
;;;   (load 1)
;;;   (isub)
;;;   (store x)
;;;   (goto for3)
;;;   break5
;;;   (load tn)
;;;   (ireturn)
;;;   (halt)))