Advertisement
Guest User

Untitled

a guest
Jul 5th, 2015
163
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.97 KB | None | 0 0
  1. #lang racket
  2.  
  3. ; Docs in infix.scrbl
  4.  
  5. (provide $ (rename-out ($ infix)) ! √ ^ € Ʃ Π)
  6. (require (only-in racket (sqrt √) (expt ^)))
  7.  
  8. ; ----------------------------------------------------------------------------------------------------
  9. ; Definition of operators and related procedures and syntax.
  10. ; These definitions can be made within transformer $ too, but as done below check-syntax and
  11. ; background expansion show binding arrows. Defined within syntax $ these binding arrows are lost.
  12.  
  13. (begin-for-syntax
  14. (require (only-in racket syntax-case with-syntax datum->syntax #%app quote syntax))
  15. (define operators (syntax->list #'(+ - * / ^ √ € ! quote unquote quasiquote Ʃ Π)))
  16. (define (operator? stx) (and (identifier? stx) (member stx operators free-identifier=?)))
  17. (define (var? stx) (and (identifier? stx) (not (member stx operators free-identifier=?))))
  18. (define (atom? stx) (syntax-case stx () ((x ...) #f) (x (not (operator? #'x)))))
  19.  
  20. (define-syntax (stx-case stx)
  21. (syntax-case stx ()
  22. ((_ stx-expr clause ...)
  23. (with-syntax
  24. ((+ (datum->syntax stx '+))
  25. (- (datum->syntax stx '-))
  26. (* (datum->syntax stx '*))
  27. (/ (datum->syntax stx '/))
  28. (^ (datum->syntax stx '^))
  29. (√ (datum->syntax stx '√))
  30. (€ (datum->syntax stx '€))
  31. (! (datum->syntax stx '!))
  32. (Ʃ (datum->syntax stx 'Ʃ))
  33. (Π (datum->syntax stx 'Π))
  34. ; (= (datum->syntax stx '=))
  35. (quote (datum->syntax stx 'quote))
  36. (unquote (datum->syntax stx 'unquote))
  37. (quasiquote (datum->syntax stx 'quasiquote)))
  38. #'(syntax-case stx-expr (+ - * / ^ √ € ! quote unquote quasiquote Ʃ Π =) clause ...))))))
  39.  
  40. ; ----------------------------------------------------------------------------------------------------
  41.  
  42. (define-syntax ($ infix-stx)
  43.  
  44. (define (main)
  45. (syntax-case infix-stx ()
  46. ((_) (infix-error "missing expr" infix-stx))
  47. ((_ x ...) (parse-expr #'(x ...)))
  48. (_ (infix-error "incorrect use of syntax infix" infix-stx))))
  49.  
  50. (define (parse-expr stx)
  51. (let-values (((pos-terms neg-terms) (parse-terms stx #f #'() #'())))
  52. (syntax-case (list pos-terms neg-terms) ()
  53. ((( ) (y )) #'(- y))
  54. ((( ) (y ...)) #'(- (+ y ...)))
  55. (((x ) ( )) #'x)
  56. (((x ) (y ...)) #'(- x y ...))
  57. (((x ...) ( )) #'(+ x ...))
  58. (((x ...) (y ...)) #'(- (+ x ...) y ...)))))
  59.  
  60. (define (parse-terms stx -? pos-terms neg-terms)
  61. (let-values (((term -? rest) (parse-term stx -?)))
  62. (let-values
  63. (((pos-terms neg-terms)
  64. (if -?
  65. (values pos-terms #`(#,@neg-terms #,term))
  66. (values #`(#,@pos-terms #,term) neg-terms))))
  67. (stx-case rest
  68. (() (values pos-terms neg-terms))
  69. ((x) (operator? #'x) (infix-error "missing element" #'x))
  70. ((+ x ...) (parse-terms #'(x ...) #f pos-terms neg-terms))
  71. ((- x ...) (parse-terms #'(x ...) #t pos-terms neg-terms))
  72. ((x y ...) (infix-error "missing operator" #'x))))))
  73.  
  74. (define (parse-term stx -?)
  75. (stx-case stx
  76. ((x) (operator? #'x) (infix-error "missing element" #'x))
  77. ((+ x ...) (parse-term #'(x ...) -?))
  78. ((- x ...) (parse-term #'(x ...) (not -?)))
  79. (_
  80. (let-values (((numerators denominators -? rest) (parse-factors stx -?)))
  81. (syntax-case (list numerators denominators) ()
  82. ((( ) (y )) (values #'(/ y) -? rest))
  83. ((( ) (y ...)) (values #'(/ (* y ...)) -? rest))
  84. (((x ) ( )) (values #'x -? rest))
  85. (((x ) (y ...)) (values #'(/ x y ...) -? rest))
  86. (((x ...) ( )) (values #'(* x ...) -? rest))
  87. (((x ...) (y ...)) (values #'(/ (* x ...) y ...) -? rest)))))))
  88.  
  89. (define (parse-factors stx -?)
  90. (define (parse-factors stx -? /? numerators denominators)
  91. (let-values (((factor -? /? rest) (parse-factor stx -? /?)))
  92. (let-values
  93. (((numerators denominators)
  94. (if /?
  95. (values numerators #`(#,@denominators #,factor))
  96. (values #`(#,@numerators #,factor) denominators))))
  97. (stx-case rest
  98. (() (values numerators denominators -? rest))
  99. ((x) (operator? #'x) (infix-error "missing element" #'x))
  100. ((* x ...) (parse-factors #'(x ...) -? /? numerators denominators))
  101. ((/ x ...) (parse-factors #'(x ...) -? (not /?) numerators denominators))
  102. (_ (values numerators denominators -? rest))))))
  103. (parse-factors stx -? #f #'() #'()))
  104.  
  105. (define (parse-factor stx -? /?)
  106. (stx-case stx
  107. (() (infix-error "missing factor" stx))
  108. ((x) (operator? #'x) (infix-error "missing element" #'x))
  109. ((* x ...) (parse-factor #'(x ...) -? /?))
  110. ((/ x ...) (parse-factor #'(x ...) -? (not /?)))
  111. ((+ x ...) (parse-factor #'(x ...) -? /?))
  112. ((- x ...) (parse-factor #'(x ...) (not -?) /?))
  113. (_ (let-values (((expt rest) (parse-expt stx))) (values expt -? /? rest)))))
  114.  
  115. (define (parse-expt stx)
  116. (let-values (((base rest) (parse-element stx)))
  117. (let loop ((stx rest) (elements #`(#,base)))
  118. (stx-case stx
  119. ((x) (operator? #'x) (infix-error "missing exponent" #'x))
  120. ((^ x ...)
  121. (let-values (((element rest) (parse-element #'(x ...))))
  122. (loop rest #`(#,@elements #,element))))
  123. (_ (values (do-expt elements) stx))))))
  124.  
  125. (define (do-expt stx)
  126. (syntax-case stx ()
  127. ((x) #'x)
  128. ((x y ...) #`(^ x #,(do-expt #'(y ...))))))
  129.  
  130. (define (parse-element stx)
  131. (define (parse-e stx -? /?)
  132. (stx-case stx
  133. (('x . rest) (do! #''x #'rest -? /?))
  134. ((`x . rest) (do! #'`x #'rest -? /?))
  135. (((x ...) . rest) (do! (parse-expr #'(x ...)) #'rest -? /?))
  136. ((Ʃ (var = x ...) . rest)
  137. (let ((range (parse-args #'(x ...))))
  138. (let-values (((body rest) (parse-element #'rest)))
  139. (values #`(for-sum var #,range #,body) rest))))
  140. ((Π (var = x ...) . rest)
  141. (let ((range (parse-args #'(x ...))))
  142. (let-values (((body rest) (parse-element #'rest)))
  143. (values #`(for-prod var #,range #,body) rest))))
  144. ((€ x (arg ...) y ...) (do! #`(x #,@(parse-args #'(arg ...))) #'(y ...) -? /?))
  145. ((€ x y ...) (do! #'x #'(y ...) -? /?))
  146. ((fun (arg ...) . rest) (var? #'fun) (do! #`(fun #,@(parse-args #'(arg ...))) #'rest -? /?))
  147. ((atom . rest) (atom? #'atom) (do! #'atom #'rest -? /?))
  148. ((x) (operator? #'x) (infix-error "missing element" (car (syntax->list stx))))
  149. ((+ x ...) (parse-e #'(x ...) -? /?))
  150. ((- x ...) (parse-e #'(x ...) (not -?) /?))
  151. ((* x ...) (parse-e #'(x ...) -? /?))
  152. ((/ x ...) (parse-e #'(x ...) -? (not /?)))
  153. ((√ x ...)
  154. (let-values (((√arg rest) (parse-element #'(x ...))))
  155. (values (do-element #`(√ #,√arg) -? /?) rest)))
  156. ((^ x ...) (infix-error "incorrect ^" (car (syntax->list stx))))
  157. ((x y ...) (infix-error "unrecognized element" #'x))))
  158. (parse-e stx #f #f))
  159.  
  160. (define (do! arg rest -? /?)
  161. (stx-case rest
  162. ((! . rest) (do! #`(! #,arg) #'rest -? /?))
  163. (_ (values (do-element arg -? /?) rest))))
  164.  
  165. (define (do-element stx -? /?)
  166. (syntax-case (list -? /?) ()
  167. ((#f #f) stx)
  168. ((#f #t) #`(/ #,stx))
  169. ((#t #f) #`(- #,stx))
  170. ((#t #t) #`(- (/ #,stx)))))
  171.  
  172. (define (parse-args stx)
  173. (define (parse-args arg stx)
  174. (stx-case stx
  175. (() (if (null? (syntax-e arg)) #'() #`(#,(parse-expr arg))))
  176. ((, x y ...)
  177. (if (null? (syntax-e arg)) (infix-error "missing argument" #'x)
  178. #`(#,(parse-expr arg) #,@(parse-args #'() #'(x y ...)))))
  179. ((x y ...) (parse-args #`(#,@arg x) #'(y ...)))))
  180. (parse-args #'() stx))
  181.  
  182. (define infix-error
  183. (case-lambda
  184. ((msg ) (infix-error msg infix-stx))
  185. ((msg stx ) (infix-error msg infix-stx stx))
  186. ((msg stx sub-stx) (raise-syntax-error 'infix msg stx sub-stx))))
  187.  
  188. (main))
  189.  
  190. ; ----------------------------------------------------------------------------------------------------
  191. ; Auxiliary definitions.
  192.  
  193. (define-syntax (for-sum stx)
  194. (syntax-case stx ()
  195. ((_ var range body) #'(for-sum/prod + 0 var range body "summation"))))
  196.  
  197. (define-syntax (for-prod stx)
  198. (syntax-case stx ()
  199. ((_ var range body) #'(for-sum/prod * 1 var range body "product"))))
  200.  
  201. (define-syntax (for-sum/prod stx)
  202. (syntax-case stx ()
  203. ((_ fun init var (from to step) body type)
  204. #'(let ((f from) (t to) (s step))
  205. (when (or (zero? s) (= (+ f s) (+ f s s)) (= (- t s) (- t s s)) (infinite? (/ (- t f) s)))
  206. (error 'infix "infinite ~a loop with from=~s, to=~s, step=~s" type f t s))
  207. (let ((<> (if (positive? s) >= <=)))
  208. (let loop ((accum init) (var f))
  209. (if (<> var t) accum
  210. (loop (fun accum body) (+ var s)))))))
  211. ((_ fun init var (from to) body type)
  212. #'(for-sum/prod fun init var (from to 1) body type))))
  213.  
  214. (define-syntax (define-dummy-syntax stx)
  215. (syntax-case stx ()
  216. ((_ s)
  217. #'(define-syntax (s dummy-stx)
  218. (syntax-case dummy-stx ()
  219. ((x y (... ...)) (raise-syntax-error 's "valid in infix exprs only" #'x))
  220. (_ (raise-syntax-error 's "valid in infix exprs only" dummy-stx)))))))
  221.  
  222. (define-dummy-syntax €)
  223. (define-dummy-syntax Ʃ)
  224. (define-dummy-syntax Π)
  225.  
  226. (define (! n)
  227. (unless (exact-nonnegative-integer? n) (raise-argument-error '! "exact-nonnegative-integer?" n))
  228. (let ! ((n n) (f 1)) (if (zero? n) f (! (sub1 n) (* n f)))))
  229.  
  230. ; The end ============================================================================================
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement