scm-arith.scm 9.3 KB

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