;; essentials

(def cons
     (fn* cons [x seq] (. com.las3r.runtime.RT (cons x seq))))

(def first
     (fn* [coll] (. com.las3r.runtime.RT (first coll))))

(def rest
     (fn* [x] (. com.las3r.runtime.RT (rest x))))

(def
 instance? (fn* [c x] (. com.las3r.runtime.RT (isInstance c x))))

(def
 seq? (fn* [x] (instance? com.las3r.runtime.ISeq x)))

(def
 vector? (fn* [x] (instance? com.las3r.runtime.IVector x)))

(def list->vector
     (fn* [list] (. com.las3r.runtime.Vector (createFromSeq list))))

;; macros

(def repeat
     (fn* [times & forms]
	  (list '. 'logo (list 'repeat
			       times
			       (list 'fn* []
				     (cons 'do forms))))))

(. (var repeat) (setMacro))

(def to
     (fn* [decl & body]
	  (list 'def (if (seq? decl) (first decl) decl) 
		(list
		 'fn* 
		 (if (seq? decl) (list->vector (rest decl)) '[])
		 (cons 'do body)))))
	  
(. (var to) (setMacro))

(def macroexpand-1
  (fn* [form]
       (. (. *runtime* compiler) (macroexpand1 form))))

;; math stuff

(def =
     (fn* [x y] (. com.las3r.util.Util (equal x y))))

(def +
     (fn* [x y] (. com.las3r.runtime.Numbers (add x y))))

(def *
     (fn* [x y] (. com.las3r.runtime.Numbers (multiply x y))))

(def /
     (fn* [x y] (. com.las3r.runtime.Numbers (divide x y))))

(def -
     (fn* [x y] (. com.las3r.runtime.Numbers (minus x y))))

(def <
     (fn* [x y] (. com.las3r.runtime.Numbers (lt x y))))

(def <=
     (fn* [x y] (. com.las3r.runtime.Numbers (lte x y))))

(def >
     (fn* [x y] (. com.las3r.runtime.Numbers (gt x y))))

(def >=
     (fn* [x y] (. com.las3r.runtime.Numbers (gte x y))))

(def ==
     (fn* [x y] (. com.las3r.runtime.Numbers (equiv x y))))

(def max
     (fn* [x y] (if (> x y) x y)))

(def min
     (fn* [x y] (if (< x y) x y)))

(def inc
     (fn* [x] (. com.las3r.runtime.Numbers (inc x))))

(def dec
     (fn* [x] (. com.las3r.runtime.Numbers (dec x))))

(def pos?
     (fn* [x] (> x 0)))

(def neg?
     (fn* [x] (< x 0)))

(def zero?
     (fn* [x] (= x 0)))

;; logo stuff

(def cs
     (fn* []
	  (. logo (cs))))

(def fd (fn* [distance]
	     (. logo (fd distance))))

(def bk (fn* [distance]
	     (fd (- 0 distance))))

(def yaw (fn* [angle] 
	      (. (. logo turtle) (yaw angle))))

(def rt yaw)
(def lt (fn* [angle]
	     (rt (- 0 angle))))

(def pitch (fn* [angle] 
		(. (. logo turtle) (pitch angle))))

(def nd pitch)
(def nu (fn* [angle]
	     (nd (- 0 angle))))

(def roll (fn* [angle] 
	       (. (. logo turtle) (roll angle))))

(def rcc roll)
(def rcw (fn* [angle]
	      (rcc (- 0 angle))))

(def pu (fn* [] 
	     (set! (. logo draw) false)))

(def pd (fn* [] 
	     (set! (. logo draw) true)))

(def setpc 
     (fn* [r g b a]
	  (. logo (setColor r g b a))))

(def setpw
     (fn* [width]
	  (set! (. logo radius) width)))

(def setpq
     (fn* [quality]
	  (set! (. logo segmentsW) quality)))

(def ht (fn* []
	     (set! (. (. logo turtle) visible) false)))

(def st (fn* []
	     (set! (. (. logo turtle) visible) true)))

(def setxyz (fn* [x y z]
		 (do
		   (set! (. (. logo turtle) x) x)
		   (set! (. (. logo turtle) y) y)
		   (set! (. (. logo turtle) z) z))))

(def home (fn* []
	       (. logo (home))))

;; demo

(to demo   
    (to (tree size branches depth)
	(if (> depth 0)
	  (do
	    (setpc (- 1 (/ 0.5 depth)) (/ 1 depth) (+ 0.5 (/ 0.5 depth)) 1)
	    (setpw (/ size 7))
	    (setpq (* depth 2))
	    (fd size)
	    (repeat branches 
		    (rcc (/ 360 branches))
		    (nd 50)
		    (tree (* 0.66 size) branches (dec depth))
		    (nu 50))
	    (pu)
	    (bk size)
	    (pd))))
    (cs)
    (pu)
    (bk 150)
    (pd)
    (tree 200 3 6)
    (setpw 1)
    (setpq 1))

(demo)

;; that's it

'ready