home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / scheme / schmlbrr / schem_lb.lha / unsupported / CScheme / misc.scm < prev    next >
Encoding:
Text File  |  1991-08-05  |  9.4 KB  |  376 lines

  1. ;;; -*- Base: 10; Mode: Scheme; Syntax: MIT Scheme; Package: USER -*-
  2. ;;
  3. ;; MISC.SCM
  4. ;;
  5. ;; July 1, 1991
  6. ;; Minghsun Liu
  7. ;;
  8. ;; Some miscellenous definitions.  (Actually, this file contains many
  9. ;; constructs that do iterations.)
  10. ;;
  11. ;;
  12. ;; The following(s) are(is) defined:
  13. ;;
  14. ;; (PUSH ITEM PLACE)
  15. ;; (MAPCAN FUNC A-LIST . MORE-LIST)
  16. ;; (WHEN TEST . FORM)
  17. ;; (LOOP . FORM)
  18. ;; (DOTIMES VAR COUNTFORM #!OPTIONAL RESULTFORM . PROGBODY)
  19. ;; (UNLESS TEST . FORM)
  20. ;; (DOLIST ITER-FORM . BODY)
  21. ;; (DO* ITERFORM ENDFORM . PROGBODY)
  22. ;; (PSETQ . ASSIGN)
  23. ;; (PROG1 . PROGBODY)
  24. ;; (PROG1-PSETQ . PROGBODY)
  25. ;; (SETQ VAR FORM)
  26. ;; (SETQQ VAR FORM)
  27. ;; (CL-STRING X)
  28. ;; (ATOM?  OBJ)
  29. ;; (SETF PLACE ITEM)
  30. ;; (SET SYM VAL)
  31. ;; (READ-LINE)
  32. ;; (CL-LENGTH OBJ)
  33. ;; (MAP-VEC VECTORS)
  34. ;; (FUNCALL FUN . ARGS)
  35. ;; (COMPILE PROC-NAME BODY)
  36. ;; (PRINT STATEMENT)
  37. ;;
  38. (declare (usual-integrations))
  39.  
  40. ;;
  41. ;; (PUSH ITEM PLACE)
  42. ;;
  43. ;; destrutively push an object onto the front of a list and returns the
  44. ;; value stored in the location specified by PLACE with ITEM consed in
  45. ;; front of it.  PLACE have to be considered a "good target" by set!.
  46. ;; (i.e. This is not an exact equivalent of PUSH in CL.)  
  47. ;;
  48. (defmacro (push item place)      
  49.   (let ((temp-var (generate-uninterned-symbol 'push)))
  50.     `(let ((,temp-var ,place))
  51.        (setf ,place (cons ,item ,temp-var)))))
  52.     
  53. ;;
  54. ;; (MAPCAN FUNC A-LIST . MORE-LIST)
  55. ;;
  56. ;; is similar to MAPCAR but uses APPEND! instead.
  57. ;;
  58. (defmacro (mapcan func a-list #!rest more-list)
  59.   `(apply append! (mapcar func a-list ,@more-list)))
  60.  
  61. ;;
  62. ;; (WHEN TEST . FORM)
  63. ;;
  64. ;; evaluate forms when a condition is true.
  65. ;;
  66. (defmacro (when test #!rest form)
  67.   `(if ,test
  68.        (begin ,@form)
  69.        '()))
  70.  
  71. ;;
  72. ;; (LOOP . FORM)
  73. ;;
  74. ;; loop through forms repeatedly.
  75. ;;
  76. (defmacro (loop #!rest forms)
  77.   (let ((repeat-till-drop (generate-uninterned-symbol 'loop)))
  78.     `(call-with-current-continuation
  79.       (lambda (exit)
  80.     (let ((return (lambda (#!rest opt-arg)
  81.             (if (default-object? opt-arg)
  82.                 (exit '())
  83.                 (exit opt-arg)))))
  84.       (define (,repeat-till-drop)
  85.         ,@forms
  86.         (,repeat-till-drop))
  87.       (,repeat-till-drop))))))
  88.  
  89. ;;
  90. ;; (DOTIMES VAR COUNTFORM RESULTFORM . PROGBODY)
  91. ;;
  92. ;; iterate over PROGBODY depend COUNTFORM which should produce an
  93. ;; integer.
  94. ;;
  95. (defmacro (dotimes mainbody #!rest progbody)
  96.   (let ((dotimes-loop (generate-uninterned-symbol 'dotimes))
  97.     (temp-var (generate-uninterned-symbol)))
  98.     `(call-with-current-continuation
  99.       (lambda (exit)
  100.     (let ((return (lambda (#!optional opt-arg) 
  101.             (if (default-object? opt-arg)
  102.                 (exit '())
  103.                 (exit opt-arg)))))
  104.       (let ,dotimes-loop 
  105.           ((,(car mainbody) 0)
  106.            (,temp-var ,(cadr mainbody)))
  107.         (cond ((<= ,temp-var ,(car mainbody))
  108.            (return ,@(cddr mainbody)))
  109.           (else
  110.            ,@progbody
  111.            (,dotimes-loop (1+ ,(car mainbody)) ,temp-var)))))))))
  112.  
  113. ;;
  114. ;; (UNLESS TEST . FORM)
  115. ;;
  116. ;; FORMS are evaluate only when TEST returns NIL.
  117. ;;
  118. (defmacro (unless test #!rest forms)
  119.   `(if ,test
  120.        #f
  121.        (begin ,@forms)))
  122.  
  123. ;;
  124. ;; (DOLIST ITER-FORM . BODY)  
  125. ;;
  126. ;; iterates over the elements of a list.
  127. ;;
  128. (defmacro (dolist iter-form #!rest body)
  129.   (let ((var (car iter-form))
  130.     (list-form (cadr iter-form))
  131.     (result (if (null? (cddr iter-form))
  132.             '()
  133.             (caddr iter-form))))
  134.     `(call-with-current-continuation
  135.       (lambda (exit)
  136.     (let ((return (lambda (#!rest opt-args) (exit opt-args))))
  137.       (for-each (lambda (,var)
  138.               ,@body)
  139.             ,list-form)
  140.       ,result)))))
  141.   
  142. ;;
  143. ;; (DO* ITERFORM ENDFORM . PROGBODY)
  144. ;;
  145. ;; iterates until test condition is met.
  146. ;;
  147. ;; P.S. Again, this is hackish and relatively expensive because of all
  148. ;; the eval that it's doing but can't think of anything else right now.
  149. ;;
  150. (defmacro (do* iterform endform #!rest progbody)
  151.   (let ((do-ast-loop (generate-uninterned-symbol 'do-star))
  152.     (test (car endform))
  153.     (result (if (null? (cdr endform))
  154.             (list '())
  155.             (cdr endform))))
  156.     `(call-with-current-continuation
  157.       (lambda (exit)
  158.     (let ((return (lambda (#!optional opt-arg) 
  159.             (if (default-object? opt-arg)
  160.                 (exit '())
  161.                 (exit opt-arg)))))
  162.       (let* ,(map (lambda (exp)
  163.             (list (car exp) (cadr exp)))
  164.               iterform)
  165.         (define (,do-ast-loop)
  166.           (if ,test 
  167.            (return (begin ,@result))
  168.            (begin ,@progbody
  169.               ,@(map
  170.                  (lambda (exp)
  171.                    (if (not (null? (cddr exp))) 
  172.                    `(set! ,(car exp) ,(caddr exp))))
  173.                  iterform) 
  174.               (,do-ast-loop))))
  175.         (,do-ast-loop)))))))
  176.  
  177. ;;
  178. ;; (PSETQ . ASSIGN)
  179. ;;
  180. ;; is intended to simulate PSETQ in CL which does parralle variable
  181. ;; assignment. 
  182. ;;
  183. (defmacro (psetq #!rest assign)
  184.   (let ((temp-var (generate-uninterned-symbol 'psetq)))
  185.     (define (transform assignments)
  186.       (if (null? (cddr assignments))
  187.       (list 'setq (car assignments) (cadr assignments))
  188.       (list 'setq 
  189.         (car assignments)
  190.         (list 'prog1-psetq
  191.               (cadr assignments) 
  192.               (transform (cddr assignments))))))
  193.     (if (null? assign)
  194.     '()
  195.     `((lambda (,temp-var) ,(transform assign) ,temp-var) '()))))
  196.  
  197. ;;
  198. ;; (PROG1 . PROGBODY)
  199. ;;
  200. ;; evalutes the PROGBODY sequentially, returning exactly one value
  201. ;; from the first.
  202. ;;
  203. (defmacro (prog1 #!rest progbody)
  204.   (let ((temp-var1 (generate-uninterned-symbol 'prog1)))
  205.     `(call-with-current-continuation
  206.       (lambda (exit)
  207.     (let ((return (lambda (#!optional opt-arg) 
  208.             (exit (if (default-object? opt-arg)
  209.                   '()
  210.                   opt-arg)))))
  211.       (let ((,temp-var1 ,(car progbody)))
  212.         ,@(cdr progbody)
  213.         (return ,temp-var1)))))))
  214.  
  215. ;;
  216. ;; (PROG1-PSETQ . PROGBODY)
  217. ;;
  218. ;; evalutes the PROGBODY sequentially, returning exactly one value
  219. ;; from the first.  (Same as PROG1-AUX but does not provide RETURN and
  220. ;; only two statements at a time only.)
  221. ;;
  222. (defmacro (prog1-psetq #!rest progbody)
  223.   `(let ()
  224.      ,(cadr progbody) 
  225.      ,(car progbody)))
  226.  
  227. ;;
  228. ;; (SETQ VAR FORM) & (SETQQ VAR FORM)
  229. ;;
  230. ;; It directly manipulates the environment structure to simulate the
  231. ;; effect of SETQ in CL: to change the value of the binding of
  232. ;; a local variable or the value of the dynamic binding (or global
  233. ;; value if there is not binding) of VAR.  (SETQQ is the complete 
  234. ;; implementation.)
  235. ;;
  236. ;; P.S. For all practical purposes, one assignment at a time is enough
  237. ;; so this is what is currently supported.
  238. ;;
  239. (defmacro (setq var form)
  240.   (let ((temp-val (generate-uninterned-symbol 'setq)))
  241.     `(let ((,temp-val ,form))
  242.        (set! ,var ,temp-val)
  243.        ,temp-val)))
  244.  
  245. (defmacro (setqq var form)
  246.   (let ((temp-val (generate-uninterned-symbol 'setq))
  247.     (temp-sym (generate-uninterned-symbol 'setq)))
  248.     `(let ((,temp-val ,form)
  249.        (,temp-sym ',var))
  250.        (if (environment-bound? (make-environment) ,temp-sym)
  251.        (set! ,var ,temp-val)
  252.        (local-assignment user-initial-environment ,temp-sym ,temp-val))
  253.        ,temp-val)))
  254.  
  255. ;;
  256. ;; (CL-STRING X)
  257. ;;
  258. ;; converts a symbol or string character X to a string.
  259. ;;
  260. (define (cl-string x)
  261.   (cond ((symbol? x) (symbol->string x))
  262.     ((char? x) (string x))
  263.     ((string? x) x)
  264.     (else '())))
  265.  
  266.  
  267. ;;
  268. ;; (SETF PLACE ITEM) & (SETF-AUX PLACE ITEM)
  269. ;;
  270. ;; tries to implement some of the functionality of SETF of CL in MIT Scheme.
  271. ;;
  272. (defmacro (setf place item)
  273.   (let ((temp (generate-uninterned-symbol 'setf)))
  274.     (cond ((atom? place)
  275.        `(setq ,place ,item))  ;; simple case.
  276.       (else
  277.        `(let ((,temp ,item))
  278.           (,(symbol-append 'set- (car place) '!) ,(cadr place) ,temp)
  279.           ,temp)))))
  280.  
  281. ;;
  282. ;; (ATOM? OBJ)
  283. ;;
  284. ;; an atom, in the CL sense, is anything that is not a pair.
  285. ;;
  286. (define (atom? obj)
  287.   (not (pair? obj)))
  288.  
  289. ;;
  290. ;; (SET SYM VAL) & (SET-AUX SYM VAL)
  291. ;;
  292. ;; unquoted assignment statement.
  293. ;;
  294. (defmacro (set sym val)
  295.   `(set-aux ,sym ,val))
  296.  
  297. (define (set-aux sym val)
  298.   (if (atom? sym)
  299.       (local-assignment user-initial-environment sym val)  ;; when it's (car '(a b c))
  300.       (local-assignment user-initial-environment (cadr sym) val))  ;; when it's (quote a)
  301.   val)
  302.  
  303. ;;
  304. ;; (READ-LINE)
  305. ;;
  306. ;; read characters terminated by newline.
  307. ;;
  308. (define (read-line)
  309.   (read-string (char-set #\newline #\linefeed #\return)))
  310.  
  311. ;;
  312. ;; (CL-LENGTH OBJ)
  313. ;;
  314. ;; is the all powerful length-measuring procedure.
  315. ;;
  316. (define (cl-length obj)
  317.   (cond ((array? obj) (vector-length (just-the-array-maam obj)))
  318.     ((vector? obj) (vector-length obj))
  319.     ((list? obj) (length obj))
  320.     ((string? obj) (string-length? obj))
  321.     (else (error "CL-LENGTH: Not a sequence" obj))))
  322.  
  323. ;;
  324. ;; (MAP-VEC FUNC VECTORS)
  325. ;;
  326. ;; extends the functionality of MAP to include not only elements of a
  327. ;; list but of vectors.  The results are returned stored in a vector
  328. ;; And for now, it can only map over one vector at a time.
  329. ;;
  330. (define (map-vec func vectors)
  331.   (let ((vector-leng (vector-length vectors)))
  332.     (define (map-vec-aux func index)
  333.       (if (> 0 index)
  334.       '()
  335.       (begin
  336.         (cons (apply func (list (vector-ref vectors index)))
  337.           (map-vec-aux func (-1+ index))))))
  338.     (list->vector (map-vec-aux func (-1+ vector-leng)))))
  339.  
  340. ;;
  341. ;; (FUNCALL FUN . ARGS)
  342. ;;
  343. ;; simulates the function FUNCALL in CL.
  344. ;;
  345. (define (funcall fun #!rest args)
  346.   (apply fun args))
  347.  
  348. ;;
  349. ;; (CL-COMPILE PROC-NAME BODY)
  350. ;;
  351. ;; compiles BODY.  (BODY can be a procedure name or lambda list.)  If name is not '(),
  352. ;; the compiled procedure will be given the name NAME.
  353. ;;
  354. (define (compile proc-name body debug?)
  355.   (if (not (procedure? body))
  356.       (set! body (eval body (the-environment))))
  357.   (if debug?
  358.       body
  359.       (if proc-name
  360.       (local-assignment user-initial-environment
  361.                 proc-name 
  362.                 (compile-procedure body))
  363.       (compile-procedure body))))
  364.  
  365. ;;
  366. ;; (PRINT STATEMENT)
  367. ;;
  368. ;; simulates the PRINT in CL.
  369. ;;
  370. (defmacro (print statement)
  371.   (let ((print-this (generate-uninterned-symbol 'print)))
  372.     `(let ((,print-this ,statement))
  373.        (write-line ,print-this)
  374.        ,print-this)))
  375.  
  376.