package jscheme;
/** Holds a string representation of some Scheme code in <TT>CODE</tt>.
* A string is better than a file because with no files, its easier to
* compress everything in the classes.jar file. For editing convenience,
* the following two perl convert from normal text to this Java quoted
* format and back again:
* <pre>
* perl -pe 's/"/\\"/g; s/(\s*)(.*?)(\s*)$/\1"\2\\n" +\n/'
* perl -pe 's/\\"/"/g; s/^(\s*)"/\1/; s/\\n" [+]//'
* </pre>
* @author Peter Norvig, peter@norvig.com http://www.norvig.com
* Copyright 1998 Peter Norvig, see http://www.norvig.com/license.html **/
public class SchemePrimitives {
public static final String CODE =
"(define call/cc call-with-current-continuation)\n" +
"(define first car)\n" +
"(define second cadr)\n" +
"(define third caddr)\n" +
"(define rest cdr)\n" +
"(define set-first! set-car!)\n" +
"(define set-rest! set-cdr!)\n" +
//;;;;;;;;;;;;;;;; Standard Scheme Macros
"(define or\n" +
"(macro args\n" +
"(if (null? args)\n" +
"#f\n" +
"(cons 'cond (map list args)))))\n" +
"(define and\n" +
"(macro args\n" +
"(cond ((null? args) #t)\n" +
"((null? (rest args)) (first args))\n" +
"(else (list 'if (first args) (cons 'and (rest args)) #f)))))\n" +
"(define quasiquote\n" +
"(macro (x)\n" +
"(define (constant? exp)\n" +
"(if (pair? exp) (eq? (car exp) 'quote) (not (symbol? exp))))\n" +
"(define (combine-skeletons left right exp)\n" +
"(cond\n" +
"((and (constant? left) (constant? right))\n" +
"(if (and (eqv? (eval left) (car exp))\n" +
"(eqv? (eval right) (cdr exp)))\n" +
"(list 'quote exp)\n" +
"(list 'quote (cons (eval left) (eval right)))))\n" +
"((null? right) (list 'list left))\n" +
"((and (pair? right) (eq? (car right) 'list))\n" +
"(cons 'list (cons left (cdr right))))\n" +
"(else (list 'cons left right))))\n" +
"(define (expand-quasiquote exp nesting)\n" +
"(cond\n" +
"((vector? exp)\n" +
"(list 'apply 'vector (expand-quasiquote (vector->list exp) nesting)))\n" +
"((not (pair? exp))\n" +
"(if (constant? exp) exp (list 'quote exp)))\n" +
"((and (eq? (car exp) 'unquote) (= (length exp) 2))\n" +
"(if (= nesting 0)\n" +
"(second exp)\n" +
"(combine-skeletons ''unquote\n" +
"(expand-quasiquote (cdr exp) (- nesting 1))\n" +
"exp)))\n" +
"((and (eq? (car exp) 'quasiquote) (= (length exp) 2))\n" +
"(combine-skeletons ''quasiquote\n" +
"(expand-quasiquote (cdr exp) (+ nesting 1))\n" +
"exp))\n" +
"((and (pair? (car exp))\n" +
"(eq? (caar exp) 'unquote-splicing)\n" +
"(= (length (car exp)) 2))\n" +
"(if (= nesting 0)\n" +
"(list 'append (second (first exp))\n" +
"(expand-quasiquote (cdr exp) nesting))\n" +
"(combine-skeletons (expand-quasiquote (car exp) (- nesting 1))\n" +
"(expand-quasiquote (cdr exp) nesting)\n" +
"exp)))\n" +
"(else (combine-skeletons (expand-quasiquote (car exp) nesting)\n" +
"(expand-quasiquote (cdr exp) nesting)\n" +
"exp))))\n" +
"(expand-quasiquote x 0)))\n" +
"\n" +
"(define let\n" +
"(macro (bindings . body)\n" +
"(define (named-let name bindings body)\n" +
"`(let ((,name #f))\n" +
"(set! ,name (lambda ,(map first bindings) . ,body))\n" +
"(,name . ,(map second bindings))))\n" +
"(if (symbol? bindings)\n" +
"(named-let bindings (first body) (rest body))\n" +
"`((lambda ,(map first bindings) . ,body) . ,(map second bindings)))))\n" +
"(define let*\n" +
"(macro (bindings . body)\n" +
"(if (null? bindings) `((lambda () . ,body))\n" +
"`(let (,(first bindings))\n" +
"(let* ,(rest bindings) . ,body)))))\n" +
"(define letrec\n" +
"(macro (bindings . body)\n" +
"(let ((vars (map first bindings))\n" +
"(vals (map second bindings)))\n" +
"`(let ,(map (lambda (var) `(,var #f)) vars)\n" +
",@(map (lambda (var val) `(set! ,var ,val)) vars vals)\n" +
". ,body))))\n" +
"(define case\n" +
"(macro (exp . cases)\n" +
"(define (do-case case)\n" +
"(cond ((not (pair? case)) (error \"bad syntax in case\" case))\n" +
"((eq? (first case) 'else) case)\n" +
"(else `((member __exp__ ',(first case)) . ,(rest case)))))\n" +
"`(let ((__exp__ ,exp)) (cond . ,(map do-case cases)))))\n" +
"(define do\n" +
"(macro (bindings test-and-result . body)\n" +
"(let ((variables (map first bindings))\n" +
"(inits (map second bindings))\n" +
"(steps (map (lambda (clause)\n" +
"(if (null? (cddr clause))\n" +
"(first clause)\n" +
"(third clause)))\n" +
"bindings))\n" +
"(test (first test-and-result))\n" +
"(result (rest test-and-result)))\n" +
"`(letrec ((__loop__\n" +
"(lambda ,variables\n" +
"(if ,test\n" +
"(begin . ,result)\n" +
"(begin\n" +
",@body\n" +
"(__loop__ . ,steps))))))\n" +
"(__loop__ . ,inits)))))\n" +
"(define delay\n" +
"(macro (exp)\n" +
"(define (make-promise proc)\n" +
"(let ((result-ready? #f)\n" +
"(result #f))\n" +
"(lambda ()\n" +
"(if result-ready?\n" +
"result\n" +
"(let ((x (proc)))\n" +
"(if result-ready?\n" +
"result\n" +
"(begin (set! result-ready? #t)\n" +
"(set! result x)\n" +
"result)))))))\n" +
"`(,make-promise (lambda () ,exp))))\n" +
//;;;;;;;;;;;;;;;; Extensions
"(define time\n" +
"(macro (exp . rest) `(time-call (lambda () ,exp) . ,rest)))\n"
;
}