scm-arith.scm 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. ;;; Ported from Scheme 48 1.9. See file COPYING for notices and license.
  2. ;;;
  3. ;;; Port Author: Andrew Whatson
  4. ;;;
  5. ;;; Original Authors: Richard Kelsey, Mike Sperber
  6. ;;;
  7. ;;; scheme48-1.9.2/ps-compiler/prescheme/primop/scm-arith.scm
  8. ;;;
  9. ;;; Arithmetic inference rules
  10. (define-module (ps-compiler prescheme primop scm-arith)
  11. #:use-module (ps-compiler prescheme primop scm-scheme))
  12. (define (arith-op-rule args node depth return?)
  13. (for-each (lambda (arg)
  14. (unify! (infer-type arg depth) type/integer node))
  15. args)
  16. type/integer)
  17. (define (arith-float-op-rule args node depth return?)
  18. (for-each (lambda (arg)
  19. (unify! (infer-type arg depth) type/float node))
  20. args)
  21. type/float)
  22. (define (arith-unsigned-integer-op-rule args node depth return?)
  23. (for-each (lambda (arg)
  24. (unify! (infer-type arg depth) type/unsigned-integer node))
  25. args)
  26. type/unsigned-integer)
  27. (define (arith-comparison-rule args node depth return?)
  28. (arith-op-rule args node depth return?)
  29. type/boolean)
  30. (define (float-comparison-rule args node depth return?)
  31. (arith-float-op-rule args node depth return?)
  32. type/boolean)
  33. (define (unsigned-integer-comparison-rule args node depth return?)
  34. (arith-unsigned-integer-op-rule args node depth return?)
  35. type/boolean)
  36. (define (integer-binop-rule args node depth return?)
  37. (check-arg-type args 0 type/integer depth node)
  38. (check-arg-type args 1 type/integer depth node)
  39. type/integer)
  40. (define (float-binop-rule args node depth return?)
  41. (check-arg-type args 0 type/float depth node)
  42. (check-arg-type args 1 type/float depth node)
  43. type/float)
  44. (define (unsigned-integer-binop-rule args node depth return?)
  45. (check-arg-type args 0 type/unsigned-integer depth node)
  46. (check-arg-type args 1 type/unsigned-integer depth node)
  47. type/unsigned-integer)
  48. (define (integer-monop-rule args node depth return?)
  49. (check-arg-type args 0 type/integer depth node)
  50. type/integer)
  51. (define (integer-comparison-rule args node depth return?)
  52. (check-arg-type args 0 type/integer depth node)
  53. type/boolean)
  54. ;;----------------------------------------------------------------
  55. ;; Arithmetic
  56. (define (nonnegative-integer? x)
  57. (and (integer? x)
  58. (not (negative? x))))
  59. (define-complex-primitive (+ . integer?) +
  60. arith-op-rule
  61. (lambda (x y) (+ x y))
  62. (lambda (args type)
  63. (if (null? args)
  64. (make-literal-node 0 type/integer)
  65. (n-ary->binary args
  66. (make-literal-node (get-prescheme-primop '+))
  67. type))))
  68. (define-complex-primitive (fl+ . real?) +
  69. arith-float-op-rule
  70. (lambda (x y) (fl+ x y))
  71. (lambda (args type)
  72. (if (null? args)
  73. (make-literal-node 0.0 type/float)
  74. (n-ary->binary args
  75. (make-literal-node (get-prescheme-primop 'fl+))
  76. type))))
  77. (define-complex-primitive (un+ . nonnegative-integer?) +
  78. arith-unsigned-integer-op-rule
  79. (lambda (x y) (un+ x y))
  80. (lambda (args type)
  81. (if (null? args)
  82. (make-literal-node 0 type/unsigned-integer)
  83. (n-ary->binary args
  84. (make-literal-node (get-prescheme-primop 'un+))
  85. type))))
  86. (define-complex-primitive (* . integer?) *
  87. arith-op-rule
  88. (lambda (x y) (* x y))
  89. (lambda (args type)
  90. (if (null? args)
  91. (make-literal-node 1)
  92. (n-ary->binary args
  93. (make-literal-node (get-prescheme-primop '*))
  94. type))))
  95. (define-complex-primitive (fl* . real?) *
  96. arith-float-op-rule
  97. (lambda (x y) (fl* x y))
  98. (lambda (args type)
  99. (if (null? args)
  100. (make-literal-node 1.0)
  101. (n-ary->binary args
  102. (make-literal-node (get-prescheme-primop 'fl*))
  103. type))))
  104. (define-complex-primitive (un* . nonnegative-integer?) *
  105. arith-unsigned-integer-op-rule
  106. (lambda (x y) (un* x y))
  107. (lambda (args type)
  108. (if (null? args)
  109. (make-literal-node 1)
  110. (n-ary->binary args
  111. (make-literal-node (get-prescheme-primop 'un*))
  112. type))))
  113. (define (subtract-action name)
  114. (lambda args
  115. (if (or (null? (cdr args))
  116. (null? (cddr args)))
  117. (apply - args)
  118. (user-error "error while evaluating: type error ~A" (cons name args)))))
  119. (define (subtract-checker type name)
  120. (lambda (args node depth return)
  121. (case (length args)
  122. ((1)
  123. (check-arg-type args 0 type depth node)
  124. type)
  125. ((2)
  126. (check-arg-type args 0 type depth node)
  127. (check-arg-type args 1 type depth node)
  128. type)
  129. (else
  130. (user-error "wrong number of arguments to ~S in ~S"
  131. name
  132. (schemify node))))))
  133. (define (subtract-maker name zero)
  134. (lambda (args type)
  135. (let ((primop (get-prescheme-primop name)))
  136. (if (null? (cdr args))
  137. (make-primop-call-node primop
  138. (list (make-literal-node zero) (car args))
  139. type)
  140. (make-primop-call-node primop args type)))))
  141. (define-complex-primitive (- integer? . integer?)
  142. (subtract-action '-)
  143. (subtract-checker type/integer '-)
  144. (lambda (x y) (- x y))
  145. (subtract-maker '- 0))
  146. (define-complex-primitive (fl- real? . real?)
  147. (subtract-action '-)
  148. (subtract-checker type/float 'fl-)
  149. (lambda (x y) (fl- x y))
  150. (subtract-maker 'fl- 0.0))
  151. (define-complex-primitive (un- nonnegative-integer? . nonnegative-integer?)
  152. (subtract-action '-)
  153. (subtract-checker type/unsigned-integer 'un-)
  154. (lambda (x y) (un- x y))
  155. (subtract-maker 'un- 0))
  156. (define (n-ary->binary args proc type)
  157. (let loop ((args args))
  158. (if (null? (cdr args))
  159. (car args)
  160. (loop (cons (make-call-node proc
  161. (list (car args) (cadr args))
  162. type)
  163. (cddr args))))))
  164. (define-syntax define-binary-primitive
  165. (syntax-rules ()
  166. ((define-binary-primitive id op predicate type-reconstruct)
  167. (define-complex-primitive (id predicate predicate) op
  168. type-reconstruct
  169. (lambda (x y) (id x y))
  170. (lambda (args type)
  171. (make-primop-call-node (get-prescheme-primop 'id) args type))))))
  172. (define-binary-primitive = = integer? arith-comparison-rule)
  173. (define-binary-primitive < < integer? arith-comparison-rule)
  174. (define-binary-primitive fl= = real? float-comparison-rule)
  175. (define-binary-primitive fl< < real? float-comparison-rule)
  176. (define-binary-primitive un= = nonnegative-integer? unsigned-integer-comparison-rule)
  177. (define-binary-primitive un< < nonnegative-integer? unsigned-integer-comparison-rule)
  178. (define-semi-primitive (> integer? integer?) >
  179. arith-comparison-rule
  180. (lambda (x y) (< y x)))
  181. (define-semi-primitive (<= integer? integer?) <=
  182. arith-comparison-rule
  183. (lambda (x y) (not (< y x))))
  184. (define-semi-primitive (>= integer? integer?) >=
  185. arith-comparison-rule
  186. (lambda (x y) (not (< x y))))
  187. (define-semi-primitive (fl> real? real?) >
  188. float-comparison-rule
  189. (lambda (x y) (fl< y x)))
  190. (define-semi-primitive (fl<= real? real?) <=
  191. float-comparison-rule
  192. (lambda (x y) (not (fl< y x))))
  193. (define-semi-primitive (fl>= real? real?) >=
  194. float-comparison-rule
  195. (lambda (x y) (not (fl< x y))))
  196. (define-semi-primitive (un> nonnegative-integer? nonnegative-integer?) >
  197. unsigned-integer-comparison-rule
  198. (lambda (x y) (un< y x)))
  199. (define-semi-primitive (un<= nonnegative-integer? nonnegative-integer?) <=
  200. unsigned-integer-comparison-rule
  201. (lambda (x y) (not (un< y x))))
  202. (define-semi-primitive (un>= nonnegative-integer? nonnegative-integer?) >=
  203. unsigned-integer-comparison-rule
  204. (lambda (x y) (not (un< x y))))
  205. (define-binary-primitive quotient quotient integer? integer-binop-rule)
  206. (define-binary-primitive unquotient quotient nonnegative-integer? unsigned-integer-binop-rule)
  207. (define-binary-primitive fl/ / real? float-binop-rule)
  208. (define-binary-primitive remainder remainder integer? integer-binop-rule)
  209. (define-binary-primitive unremainder remainder nonnegative-integer? integer-binop-rule)
  210. (define-binary-primitive modulo modulo integer? integer-binop-rule)
  211. (define-primitive bitwise-and
  212. ((integer? type/integer) (integer? type/integer))
  213. type/integer)
  214. (define-primitive bitwise-ior
  215. ((integer? type/integer) (integer? type/integer))
  216. type/integer)
  217. (define-primitive bitwise-xor
  218. ((integer? type/integer) (integer? type/integer))
  219. type/integer)
  220. (define-primitive bitwise-not
  221. ((integer? type/integer))
  222. type/integer)
  223. (define-primitive shift-left
  224. ((integer? type/integer) (integer? type/integer))
  225. type/integer
  226. ashl)
  227. (define-primitive logical-shift-right
  228. ((integer? type/integer) (integer? type/integer))
  229. type/integer
  230. lshr)
  231. (define-primitive arithmetic-shift-right
  232. ((integer? type/integer) (integer? type/integer))
  233. type/integer
  234. ashr)
  235. (define-semi-primitive (abs integer?) abs
  236. arith-op-rule
  237. (lambda (n) (if (< n 0) (- 0 n) n)))
  238. (define-semi-primitive (zero? integer?) zero?
  239. arith-comparison-rule
  240. (lambda (n) (= n 0)))
  241. (define-semi-primitive (positive? integer?) positive?
  242. arith-comparison-rule
  243. (lambda (n) (< 0 n)))
  244. (define-semi-primitive (negative? integer?) negative?
  245. arith-comparison-rule
  246. (lambda (n) (< n 0)))
  247. (define-semi-primitive (even? integer?) even?
  248. integer-comparison-rule
  249. (lambda (n) (= 0 (remainder n 2))))
  250. (define-semi-primitive (odd? integer?) odd?
  251. integer-comparison-rule
  252. (lambda (n) (not (even? n))))
  253. (define-semi-primitive (max integer? . integer?) max
  254. arith-op-rule
  255. (lambda (x y)
  256. (if (< x y) y x)))
  257. (define-semi-primitive (min integer? . integer?) min
  258. arith-op-rule
  259. (lambda (x y)
  260. (if (< x y) x y)))
  261. (define-semi-primitive (expt integer? positive-integer?) expt
  262. arith-op-rule
  263. (lambda (x y)
  264. (do ((r x (* r x))
  265. (y y (- y 1)))
  266. ((<= y 0)
  267. r))))
  268. (define (unsigned->integer x) x)
  269. (define (integer->unsigned x) x)
  270. (define-primitive unsigned->integer ((nonnegative-integer? type/unsigned-integer)) type/integer)
  271. (define-primitive integer->unsigned ((integer? type/integer)) type/unsigned-integer)