;;; derivedexpressions.scm 
;;;
;;; Derived expression transformations
;;;
;;; Copyright (C) 2002 Anton van Straaten <anton@ppsolutions.com>
;;;
;;; This program is free software; you can redistribute it and/or
;;; modify it under the terms of the GNU General Public License, 
;;; version 2, as published by the Free Software Foundation.
;;;
;;; This program is distributed in the hope that it will be useful, 
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with this program; if not, see http://www.gnu.org/copyleft/gpl.html
;;;
;;; -------------------------------------------------------------------------
;;;
;;;
;;;
;;; It would be convenient to use quasiquote for the syntactic 
;;; transformations in this module, but LAML doesn't support it. 
;;;
;;; todo: instead of #f as initial values below, use 'undefined'.  However,
;;; will then need an expressable representation, even if only internal.
;;;
;;; TODO: let*
;;;
;;; (let* ((a x)
       ;;; (b y)
       ;;; (c z))
  ;;; body
  ;;; ...)
;;;
;;; =>
;;;
;;; ((lambda (a)
   ;;; ((lambda (b)  
      ;;; ((lambda (c)
         ;;; body) z)) y)) x)

Show source file in small font In derived-expressions: Link from expression-meaning-begin to it's cross reference table entry 4.7. Derived Expressions
(define (expression-meaning-begin e*) (expression-meaning-application (cons 'lambda (cons '() e*)) (ds:sequence))) ;; convert-let-variables - support procedure for 'let' transformations ;; ;; Convert the variable/value list for the let family of expressions ;; into a lists of names and values. Returns (names . values). ;; ;; Note this reverses the order of both the variables and values. This ;; maintains correlation, so is mostly acceptable for let & letrec. However, ;; named let and let* require evaluation sequence to be respected, and must ;; use reverse to obtain desired correct sequence. Show source file in small font In derived-expressions: Link from convert-let-variables to it's cross reference table entry 4.7. Derived Expressions
(define (convert-let-variables v*) (let loop ((names '()) (values '()) (v* v*)) (if (null? v*) (cons names values) (loop (cons (caar v*) names) (cons (cadar v*) values) (cdr v*))))) ;; Transform plain 'let' ;; ;; (let ((a x) ;; (b y) ;; (c z)) ;; body1 ;; body2 ;; ...) ;; ;; => ;; ;; ((lambda (a b c)) ;; body1 ;; body2 ;; ...) ;; x y z) ;; ;; Applies argument values to appropriately constructed lambda expression Show source file in small font In derived-expressions: Link from expression-meaning-let to it's cross reference table entry 4.7. Derived Expressions
(define (expression-meaning-let v* e*) (let* ((names-values (convert-let-variables v*)) (names (car names-values)) (values (cdr names-values))) (expression-meaning-application (cons 'lambda (cons names e*)) values))) ;; Transform named 'let' ;; ;; (let name ((names values)...) ;; expr ;; ...) ;; ;; => ;; ;; ((lambda (name) ;; (set! name ;; (lambda (names...) ;; expr ;; ...)) ;; (name values...)) ;; ds:undefined) Show source file in small font In derived-expressions: Link from expression-meaning-named-let to it's cross reference table entry 4.7. Derived Expressions
(define (expression-meaning-named-let name v* e*) (let* ((params-values (convert-let-variables v*)) (params (reverse (car params-values))) (values (reverse (cdr params-values)))) (expression-meaning-application (list 'lambda (list name) (list 'set! name (cons 'lambda (cons params e*))) (cons name values)) '(#f)))) ;; Transform 'letrec': ;; ;; (letrec ((a x) ;; (b y)) ;; body ;; ...) ;; ;; => ;; ;; ((lambda (a b) ;; (set! a x) ;; (set! b y) ;; body) ;; <undefined>...) ;; ;; TODO: R5RS requires something more like: ;; ;; ((lambda (a b) ;; (let ((a-temp x) ;; (b-temp y)) ;; (set! a a-temp) ;; (set! b b-temp)) ;; body) ;; <undefined>...)Show source file in small font In derived-expressions: Link from transform-letrec to it's cross reference table entry 4.7. Derived Expressions
(define (transform-letrec names values e*) (cons (cons 'lambda (cons names (append (reverse (map (lambda (i v) (list 'set! i v)) names values)) e*))) (map (lambda (v) #f) values))) Show source file in small font In derived-expressions: Link from expression-meaning-letrec to it's cross reference table entry 4.7. Derived Expressions
(define (expression-meaning-letrec v* e*) (let* ((names-values (convert-let-variables v*)) (names (car names-values)) (values (cdr names-values)) (expr (transform-letrec names values e*))) (expression-meaning-application (car expr) (cdr expr)))) ;; transform-internal-definitions is called with a lambda expression, ;; minus the 'lambda', i.e. (([args...]) [cmds...] expr). The command ;; list may contain zero or more internal definitions. This procedure ;; converts any such definitions into a letrec-like lambda form. ;; ;; todo: improve syntax validation: defines with no expr, defines in body Show source file in small font In derived-expressions: Link from transform-internal-definitions to it's cross reference table entry 4.7. Derived Expressions
(define (transform-internal-definitions e*) (if (< (length e*) 2) (malformed-expression 'lambda) (let ((param-names (ds:first e*)) (body-commands (ds:rest e*))) (let loop ((commands body-commands) (names '()) (values '())) (let ((command (ds:first commands))) (if (and (pair? command) (eq? (ds:first command) 'define)) ; it's a define; first check the type (let ((sig (ds:second command))) (if (pair? sig) ; it's a procedure definition (loop (ds:rest commands) (cons (ds:first sig) names) (cons (cons 'lambda (cons (ds:rest sig) (cddr command))) values)) ; it's a simple definition (loop (ds:rest commands) (cons sig names) (cons (ds:third command) values)))) ; got it, return final expression (if (null? names) ; no defines, return unaltered e* ; convert to letrec-style lambda, embedded within the current lambda (list param-names (transform-letrec names values commands)))))))))