primitives.scm 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. ;;; primitives.scm -- primitive operators for Joy.
  2. ;;; Copyright © 2016 Eric Bavier <bavier@member.fsf.org>
  3. ;;;
  4. ;;; Joy is free software; you can redistribute it and/or modify it under
  5. ;;; the terms of the GNU General Public License as published by the Free
  6. ;;; Software Foundation; either version 3 of the License, or (at your
  7. ;;; option) any later version.
  8. ;;;
  9. ;;; Joy is distributed in the hope that it will be useful, but WITHOUT
  10. ;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  11. ;;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  12. ;;; License for more details.
  13. ;;;
  14. ;;; You should have received a copy of the GNU General Public License
  15. ;;; along with Joy. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;;;
  18. ;;; All Joy procedures take a stack argument and return a stack
  19. ;;; argument. It's convenient for primitives to use Scheme "rest"
  20. ;;; arguments to deconstruct the expected number of arguments.
  21. (define-module (language joy primitives)
  22. #:use-module ((system base compile)
  23. #:select (compiled-file-name compile-file))
  24. #:use-module ((guile)
  25. #:select (load-compiled string-append and=>))
  26. #:use-module ((ice-9 safe-r5rs)
  27. #:select (+ - < > eqv? display list->string)
  28. #:renamer (symbol-prefix-proc '%))
  29. #:use-module ((srfi srfi-1)
  30. #:select (cons fold every)
  31. #:renamer (symbol-prefix-proc '%))
  32. #:use-module (srfi srfi-2)
  33. #:use-module (language joy write)
  34. #:replace (cons + - < > =)
  35. #:export (uncons
  36. swap
  37. dup
  38. pop
  39. choice
  40. infra
  41. stack
  42. unstack
  43. ;; IO
  44. putch
  45. putchars
  46. write
  47. #{.}#
  48. include
  49. ;; datatype inquiry
  50. logical
  51. char
  52. integer
  53. string
  54. list
  55. ;; variable definition
  56. def
  57. exit))
  58. ;;; Code:
  59. (define (->truth b)
  60. (if b 'true 'false))
  61. ;;; TODO: This could be written in base in terms of '='.
  62. (define (logical x . S)
  63. (%cons (->truth (if (eq? x 'true)
  64. #t
  65. (eq? x 'false))) S))
  66. (define (char x . S)
  67. (%cons (->truth (char? x)) S))
  68. (define (integer x . S)
  69. (%cons (->truth (integer? x)) S))
  70. (define (string x . S)
  71. (%cons (->truth (and (list? x) (%every char? x)))
  72. S))
  73. (define (list x . S)
  74. (%cons (->truth (list? x)) S))
  75. (define (cons lst x . S)
  76. (%cons (%cons x lst) S))
  77. (define (uncons lst . S)
  78. (%cons (cdr lst) (%cons (car lst) S)))
  79. (define (swap x y . S)
  80. (%cons y (%cons x S)))
  81. (define (dup x . S)
  82. (%cons x (%cons x S)))
  83. (define (pop _ . S)
  84. S)
  85. (define (+ x y . S)
  86. (%cons (%+ y x) S))
  87. (define (- x y . S)
  88. (%cons (%- y x) S))
  89. (define (< x y . S)
  90. (%cons (->truth (%< y x)) S))
  91. (define (> x y . S)
  92. (%cons (->truth (%> y x)) S))
  93. (define (= x y . S)
  94. (%cons (->truth (%eqv? x y)) S))
  95. (define (choice y x b . S)
  96. (%cons (if (eq? b 'true) x y) S))
  97. (define (infra q lst . S)
  98. (%cons (%fold (@ (language joy eval) eval) lst q)
  99. S))
  100. (define (stack . S)
  101. (%cons S S))
  102. (define (unstack S . _)
  103. S)
  104. (define (putch c . S)
  105. (write-char c)
  106. S)
  107. ;;; TODO: This could be written in base in terms of putch.
  108. (define (putchars x . S)
  109. (%display (list->string x))
  110. S)
  111. (define (write x . S)
  112. (write-joy x)
  113. S)
  114. (define #{.}# write)
  115. (define (include str . S)
  116. (and-let* ((s (list->string str))
  117. (f (search-path %load-path s '("" ".joy")))
  118. (go (compiled-file-name f)))
  119. (if go
  120. (begin
  121. (compile-file f #:output-file go #:from 'joy)
  122. (apply (load-compiled go) S))
  123. (error "could not find file to include:" s))))
  124. (define (def body sym . S)
  125. (module-define! (resolve-module '(joy))
  126. (car sym) ;item is list-quoted
  127. body)
  128. S)
  129. (define (exit status . _)
  130. "Immediately exit the program with STATUS."
  131. (primitive-exit status))
  132. ;;; For efficiency, having low-level implementations of the following
  133. ;;; might be beneficial (though I have yet to prove this in practice):
  134. ;;;
  135. ;;; i dip dipd popd dupd swapd times divmod / * % <= >= max min true false and
  136. ;;; or not null branch ifte
  137. ;;;
  138. ;;; In particular, it seems the dip and i combinators would be
  139. ;;; especially beneficial. Or just dip if we use 'i == dup dip pop'.