rpn.lisp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. (load "./list.lisp")
  2. (load "./math.lisp")
  3. (defvar *stack* '())
  4. (defun clear-operand! ()
  5. (let ((elem ((@ document get-element-by-id) "operand")))
  6. (setf (@ elem inner-H-T-M-L) "")))
  7. (defun add-to-stack! ()
  8. (let* ((elem ((@ document get-element-by-id) "operand"))
  9. (value (@ elem inner-H-T-M-L)))
  10. (if (string= value "")
  11. (setf *stack* (append (list (car *stack*)) *stack*))
  12. (setf *stack* (append (list value) *stack*)))
  13. (clear-operand!)))
  14. (defun remove-from-stack (n)
  15. (let ((new-stack *stack*))
  16. (dotimes (i n)
  17. (setf new-stack (cdr new-stack) ))
  18. new-stack))
  19. (defun render-stack! ()
  20. (let* ((e ((@ document get-element-by-id) "stack"))
  21. (left-softkey ((@ document get-element-by-id) "left"))
  22. (i (length *stack*))
  23. (html (if (zero? i)
  24. ""
  25. (reduce
  26. (lambda (a c)
  27. (setf i (1- i))
  28. (let* ((body (concatenate 'string i ": " c))
  29. (n (ps-html
  30. ((:div :id c
  31. :class "stack-item")
  32. body))))
  33. (if (eq 'start a)
  34. n
  35. (concatenate 'string a n))))
  36. (reverse *stack*)
  37. 'start))))
  38. (setf (@ left-softkey inner-H-T-M-L) "Drop")
  39. (setf (@ e inner-H-T-M-L) html)))
  40. (defun do-operation! (operation number-required)
  41. (let ((elem ((@ document get-element-by-id) "operand")))
  42. (if (string= (@ elem inner-H-T-M-L) "")
  43. (if (or (null? *stack*)
  44. (< (length *stack*) number-required))
  45. (error (concatenate 'string
  46. "Need "
  47. number-required
  48. " items in the stack to preform "
  49. (symbol-to-js-string operation)))
  50. (let* ((operands (subseq *stack* 0 number-required))
  51. (numerical-answer (if (= 1 (length operands))
  52. (operation (-Number (car operands)))
  53. (reduce
  54. (lambda (a c)
  55. (let ((na (-Number a))
  56. (nc (-Number c)))
  57. (cond
  58. ((and a c)
  59. (operation na nc))
  60. (a
  61. (operation na))
  62. (c
  63. (operation nc))
  64. (otherwise
  65. a))))
  66. operands)))
  67. (answer (-String numerical-answer))
  68. (stack-without (remove-from-stack number-required)))
  69. (setf *stack* (append (list answer) stack-without))))
  70. (if (null? *stack*)
  71. (error (concatenate 'string
  72. "Need "
  73. (1- number-required)
  74. " items in the stack to preform "
  75. (symbol-to-js-string operation)))
  76. (let* ((elem ((@ document get-element-by-id) "operand"))
  77. (stack (append (list (@ elem inner-H-T-M-L)) *stack*))
  78. (operands (reverse (subseq stack 0 number-required))) ;for operations that don't have the associative property
  79. (numerical-answer (if (= 1 (length operands))
  80. (operation (-Number (car operands)))
  81. (reduce
  82. (lambda (a c)
  83. (let ((na (-Number a))
  84. (nc (-Number c)))
  85. (cond
  86. ((and a c)
  87. (operation na nc))
  88. (a
  89. (operation na))
  90. (c
  91. (operation nc))
  92. (otherwise
  93. a))))
  94. operands)))
  95. (answer (-String numerical-answer))
  96. (stack-without (remove-from-stack (1- number-required))))
  97. (setf *stack* (append (list answer) stack-without)))))
  98. (render-stack!)
  99. (clear-operand!)))
  100. (defun clear-all! ()
  101. (setf *stack* (list))
  102. (render-stack!))
  103. (chain
  104. document
  105. (add-event-listener
  106. "keydown"
  107. (lambda (e)
  108. ;; ((@ e prevent-default))
  109. (let ((key (@ e key)))
  110. (case key
  111. ("Enter"
  112. (progn
  113. (add-to-stack!)
  114. (render-stack!)))
  115. ("ArrowDown"
  116. (do-operation! (lambda (x y) (+ x y)) 2))
  117. ("ArrowUp"
  118. (do-operation! (lambda (x y) (- x y)) 2))
  119. ("ArrowRight"
  120. (do-operation! (lambda (x y) (* x y)) 2))
  121. ("ArrowLeft"
  122. (do-operation! (lambda (x y) (/ x y)) 2))
  123. ("#"
  124. (do-operation! (lambda (x) (* x -1)) 1))
  125. ("*"
  126. (let* ((input ((@ document get-element-by-id) "operand"))
  127. (value (@ input inner-H-T-M-L)))
  128. (setf (@ input inner-H-T-M-L) (concatenate 'string value "."))))
  129. ("SoftLeft"
  130. (let ((input ((@ document get-element-by-id) "operand")))
  131. (if (string= (@ input inner-H-T-M-L) "")
  132. (progn
  133. (setf *stack* (cdr *stack*))
  134. (render-stack!))
  135. (clear-operand!))))
  136. ("SoftRight" ;preform a swap
  137. (when (>= (length *stack*) 2)
  138. (let ((fir (car *stack*))
  139. (sec (cadr *stack*)))
  140. (setf *stack* (append (list sec fir) (cddr *stack*)))
  141. (render-stack!))))
  142. ("Call" ;preform a roll
  143. (when (>= (length *stack*) 2)
  144. (let ((fir (car *stack*)))
  145. (setf *stack* (append (cdr *stack*) (list fir)))
  146. (render-stack!))))
  147. ("Backspace"
  148. (close))
  149. ("MicrophoneToggle"
  150. nil)
  151. (otherwise
  152. (let* ((input ((@ document get-element-by-id) "operand"))
  153. (left-softkey ((@ document get-element-by-id) "left"))
  154. (value (@ input inner-H-T-M-L)))
  155. (setf (@ left-softkey inner-H-T-M-L) "Clear")
  156. (if value
  157. (setf (@ input inner-H-T-M-L) (concatenate 'string value key))
  158. (setf (@ input inner-H-T-M-L) (concatenate 'string key))))))))))
  159. (chain
  160. document
  161. (add-event-listener
  162. "DOMContentLoaded"
  163. (lambda ()
  164. (let ((input ((@ document get-element-by-id) "operand"))
  165. (left-softkey ((@ document get-element-by-id) "left"))
  166. (enter-key ((@ document get-element-by-id) "middle"))
  167. (right-softkey ((@ document get-element-by-id) "right")))
  168. (setf (@ input inner-H-T-M-L) "")
  169. (setf (@ left-softkey inner-H-T-M-L) "Drop")
  170. (setf (@ enter-key inner-H-T-M-L) "ENTER")
  171. (setf (@ right-softkey inner-H-T-M-L) "Swap")))))