anchor.diff: +;;
  +;; Macro Preprocessor for High Productivity (MacroPHP)
   ;; Copyright (c) 2009 Valeriy Zamarayev
  +;;
   
   (defpackage :php (:use :cl))
   
  
positive.code: (defspecialform (if cond true false)
    (fmt "if (~W) ~/pprint-block/ else ~/pprint-block/" cond (list true) (list false)))
  
  ;; how do we map lisp expressions to PHP ones
  (loop
     for ops in (reverse
  	       ;; op php-op associativity arity
  	       '(((not ! :right 1))
  		 ((/ / :left 2)
  		  (* * :left 2)
  		  (mod % :left 2))
  		 ((+ + :left 2)
  		  (- - :left 2))
  		 ((concat \. :left 2))
  		 ((<< << :left 2)
  		  (>> >> :left 2))
  		 ((< < :left 2)
  		  (<= <= :none 2)
  		  (> > :none 2)
  		  (>= >= :none 2))
  		 ((/= != :none 2)
  		  (= = :none 2))
  		 ((ref & :left 1))
  		 ((logand & :left 2))
  		 ((logxor ^ :left 2))
  		 ((logior \| :left 2))
  		 ((and && :left 2))
  		 ((setq = :right 2))
  		 ((or \|\| :left 2))))
     for k from 0
     do (loop for (op php-op assoc arity) in ops
  	 do
  	   (setf (get op :php-op) php-op)
  	   (setf (get op :associativity) assoc)
  	   (setf (get op :arity) arity)
  	   (setf (get op :precedence) k)))
  
  (defun php-op (exp)
    (and (consp exp)
         (symbolp (car exp))
         (get (car exp) :php-op)))
  
  (defun associativity (exp)
    (get (car exp) :associativity))
  
  (defun precedence (exp)
    (get (car exp) :precedence))
  
  (defun arity (exp)
    (get (car exp) :arity))
  
  (defun unary-p (exp)
    (= 1 (arity exp)))
  
  (defun binary-p (exp)
    (= 2 (arity exp)))
  
  (defun pprint-php-exp (s op)
    (let ((nest (<= (precedence op) *B*)))
      (flet ((write-op ()
  	     (write-string (string-downcase (symbol-name (php-op op))) s)))
        (pprint-logical-block (s (cdr op) :prefix (if nest "(" "") :suffix (if nest ")" ""))
  	(cond ((unary-p op)
  	       ;; TODO: convert those asserts into throwing of
  	       ;; compilation errors
  	       (assert (= 2 (length op)))
  	       (let ((*B* (precedence op)))
  		 (write-op)
  		 (write (pprint-pop) :stream s)))
  	      ((binary-p op)
  	       (assert (= 3 (length op)))
  	       (let ((*B*
  		      (if (eq :left (associativity op))
  			  (1- (precedence op))
  			  (precedence op))))
  		 (write (pprint-pop) :stream s))
  	       (write-char #\Space s)
  	       (write-op)
  	       (write-char #\Space s)
  	       (pprint-indent :block 4 s)
  	       (pprint-newline :fill s)
  	       (let ((*B*
  		      (if (eq :right (associativity op))
  			  (1- (precedence op))
  			  (precedence op))))
  		 (write (pprint-pop) :stream s))))))))
  
  (defprinter ((satisfies php-op) exp)
    (pprint-php-exp stream exp))
  
  ;; TODO rest of assingment ops
  ;; should be like optimized stuff from others
  
negative.code: 
  (defmacro defspecialform (form &body body)
    (let ((arg (gensym)))
      `(set-php-pprint-dispatch '(cons (member ,(first form)))
  			  (lambda (stream ,arg)
  			    (destructuring-bind ,form ,arg
  			      (declare (ignorable ,(first form)))
  			      (macrolet ((fmt (&rest args) `(format stream ,@args))
  					 (write-str (arg) `(cl:write-string ,arg stream)))
  				,@body))))))
    
  (defun pprint-block (stream block &optional colon at-sign)
    (declare (ignore colon at-sign))
  