;;; -*-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-macro (begin . rest) `((lambda () ,@rest))) (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)))) (#t (eq? a b)))) (define (vector . rest) (list->vector rest)) (define (apply f args) (c:eval (cons f args) (current-module))) (define (defined? x) (assq x (current-module))) (define (procedure? p) (cond ((builtin? p) #t) ((pair? p) (eq? (car p) 'lambda)) (#t #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-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 (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 bindings-or-label . rest) `(if ,(symbol? bindings-or-label) (let-loop ,bindings-or-label ,(car rest) ,(cdr rest)) (simple-let ,bindings-or-label ,rest))) (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 (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 ((val (number->string counter))) ;; (set! counter (+ counter 1)) ;; (string->symbol (string-append "g" val))))))