;;; -*-scheme-*- ;;; Mes --- Maxwell Equations of Software ;;; Copyright © 2016 Jan Nieuwenhuizen ;;; ;;; scm.mes: This file is part of Mes. ;;; ;;; Mes is free software; you can redistribute it and/or modify it ;;; under the terms of the GNU General Public License as published by ;;; the Free Software Foundation; either version 3 of the License, or (at ;;; your option) any later version. ;;; ;;; Mes 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 Mes. If not, see . ;; The Maxwell Equations of Software -- John McCarthy page 13 ;; http://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf (define (list . rest) rest) (define (split-params bindings params) (cond ((null? bindings) params) (#t (split-params (cdr bindings) (append params (cons (caar bindings) '())))))) (define (split-values bindings values) (cond ((null? bindings) values) (#t (split-values (cdr bindings) (append values (cdar bindings) '()))))) (define-macro (simple-let bindings rest) `((lambda ,(split-params bindings '()) ,@rest) ,@(split-values bindings '()))) (define-macro (let-loop label bindings . rest) `(let ((,label *unspecified*)) (let ((,label (lambda ,(split-params bindings '()) ,@rest))) (,label ,@(split-values bindings '()))))) (define-macro (let-loop label bindings rest) `((lambda (,label) (set! ,label (lambda ,(split-params bindings '()) ,@rest)) (,label ,@(split-values bindings '()))) *unspecified*)) (define-macro (let bindings-or-label . rest) `(cond (,(symbol? bindings-or-label) (let-loop ,bindings-or-label ,(car rest) ,(cdr rest))) (#t (simple-let ,bindings-or-label ,rest)))) (define-macro (or2 x y) `(cond (,x ,x) (#t ,y))) (define-macro (and2 x y) `(cond (,x ,y) (#t #f))) (define-macro (or . x) (cond ((null? x) #f) ((null? (cdr x)) (car x)) (#t `(cond (,(car x)) (#t (or ,@(cdr x))))))) (define-macro (and . x) (cond ((null? x) #t) ((null? (cdr x)) (car x)) (#t `(cond (,(car x) (and ,@(cdr x))) (#t #f))))) (define (expand-let* bindings body) (cond ((null? bindings) `((lambda () ,@body))) (#t `((lambda (,(caar bindings)) ,(expand-let* (cdr bindings) body)) ,@(cdar bindings))))) (define-macro (let* bindings . body) (expand-let* bindings body)) (define (equal? a b) ;; FIXME: only 2 arg (cond ((and (null? a) (null? b)) #t) ((and (pair? a) (pair? b)) (and (equal? (car a) (car b)) (equal? (cdr a) (cdr b)))) ((and (string? a) (string? b)) (eq? (string->symbol a) (string->symbol b))) ((and (vector? a) (vector? b)) (equal? (vector->list a) (vector->list b))) (#t (eq? a b)))) (define (vector . rest) (list->vector rest)) (define (make-vector n . x) (let ((fill (if (pair? x) (cdr x) *unspecified*))) (list->vector (let loop ((n n)) (if (= 0 n) '() (cons fill (loop (- n 1)))))))) (define (apply f args) (eval (cons f args) (current-module))) (define-macro (defined? x) `(assq ,x (cddr (current-module)))) (define (procedure? p) (cond ((builtin? p) #t) ((and (pair? p) (eq? (car p) 'lambda))) ((and (pair? p) (eq? (car p) '*lambda*))) (#t #f))) (define (assq-set! alist key val) (let ((entry (assq key alist))) (cond (entry (set-cdr! entry val) alist) (#t (cons (cons key val) alist))))) (define (assq-ref alist key) (let ((entry (assq key alist))) (if entry (cdr entry) #f))) (define assv assq) (define (memq x lst) (cond ((null? lst) #f) ((eq? x (car lst)) lst) (#t (memq x (cdr lst))))) (define memv memq) (define (member x lst) (cond ((null? lst) #f) ((equal? x (car lst)) lst) (#t (member x (cdr lst))))) (define (map f l . r) (cond ((null? l) '()) ((null? r) (cons (f (car l)) (map f (cdr l)))) ((null? (cdr r)) (cons (f (car l) (caar r)) (map f (cdr l) (cdar r)))))) (define (identity x) x) (define (for-each f l . r) (apply map (cons f (cons l r))) *unspecified*) (define (not x) (cond (x #f) (#t #t))) (define (<= a b) ;; FIXME: only 2 arg (or (< a b) (= a b))) (define (>= a b) ;; FIXME: only 2 arg (or (> a b) (= a b))) (define (list? x) (or (null? x) (and (pair? x) (list? (cdr x))))) (define-macro (if expr then . else) `(cond (,expr ,then) (#t (cond (,(pair? else) ((lambda () ,@else))))))) (define-macro (when expr . body) `(if ,expr ((lambda () ,@body)))) (define (unspecified-bindings bindings params) (cond ((null? bindings) params) (#t (unspecified-bindings (cdr bindings) (append params (cons (cons (caar bindings) '(*unspecified*)) '())))))) (define (letrec-setters bindings setters) (cond ((null? bindings) setters) (#t (letrec-setters (cdr bindings) (append setters (cons (cons 'set! (car bindings)) '())))))) (define-macro (letrec bindings . body) `(let ,(unspecified-bindings bindings '()) ,@(letrec-setters bindings '()) ,@body)) ;; TODO ;; (define gensym ;; (let ((counter 0)) ;; (lambda (. rest) ;; (let ((value (number->string counter))) ;; (set! counter (+ counter 1)) ;; (string->symbol (string-append "g" value)))))) (define gensym #f) (let ((counter 0)) (set! gensym (lambda (. rest) (let ((value (number->string counter))) (set! counter (+ counter 1)) (string->symbol (string-append "g" value)))))) ;; srfi-1 (define (last-pair lst) (let loop ((lst lst)) (if (or (null? lst) (null? (cdr lst))) lst (loop (cdr lst))))) (define else #t) (define (unspecific) (if #f #f))