221 lines
17 KiB
C
221 lines
17 KiB
C
#include "picrin.h"
|
|
#include "picrin/extra.h"
|
|
|
|
static const char boot_rom[][80] = {
|
|
"(builtin:define-macro call-with-current-environment (builtin:lambda (form env) (",
|
|
"list (cadr form) env))) (builtin:define here (call-with-current-environment (bui",
|
|
"ltin:lambda (env) env))) (builtin:define the (builtin:lambda (var) (make-identif",
|
|
"ier var here))) (builtin:define the-builtin-define (the (builtin:quote builtin:d",
|
|
"efine))) (builtin:define the-builtin-lambda (the (builtin:quote builtin:lambda))",
|
|
") (builtin:define the-builtin-begin (the (builtin:quote builtin:begin))) (builti",
|
|
"n:define the-builtin-quote (the (builtin:quote builtin:quote))) (builtin:define ",
|
|
"the-builtin-set! (the (builtin:quote builtin:set!))) (builtin:define the-builtin",
|
|
"-if (the (builtin:quote builtin:if))) (builtin:define the-builtin-define-macro (",
|
|
"the (builtin:quote builtin:define-macro))) (builtin:define the-define (the (buil",
|
|
"tin:quote define))) (builtin:define the-lambda (the (builtin:quote lambda))) (bu",
|
|
"iltin:define the-begin (the (builtin:quote begin))) (builtin:define the-quote (t",
|
|
"he (builtin:quote quote))) (builtin:define the-set! (the (builtin:quote set!))) ",
|
|
"(builtin:define the-if (the (builtin:quote if))) (builtin:define the-define-macr",
|
|
"o (the (builtin:quote define-macro))) (builtin:define-macro quote (builtin:lambd",
|
|
"a (form env) (builtin:if (= (length form) 2) (list the-builtin-quote (cadr form)",
|
|
") (error \"illegal quote form\" form)))) (builtin:define-macro if (builtin:lambda ",
|
|
"(form env) ((builtin:lambda (len) (builtin:if (= len 4) (cons the-builtin-if (cd",
|
|
"r form)) (builtin:if (= len 3) (list the-builtin-if (list-ref form 1) (list-ref ",
|
|
"form 2) #undefined) (error \"illegal if form\" form)))) (length form)))) (builtin:",
|
|
"define-macro begin (builtin:lambda (form env) ((builtin:lambda (len) (if (= len ",
|
|
"1) #undefined (if (= len 2) (cadr form) (if (= len 3) (cons the-builtin-begin (c",
|
|
"dr form)) (list the-builtin-begin (cadr form) (cons the-begin (cddr form))))))) ",
|
|
"(length form)))) (builtin:define-macro set! (builtin:lambda (form env) (if (= (l",
|
|
"ength form) 3) (if (identifier? (cadr form)) (cons the-builtin-set! (cdr form)) ",
|
|
"(error \"illegal set! form\" form)) (error \"illegal set! form\" form)))) (builtin:d",
|
|
"efine check-formal (builtin:lambda (formal) (if (null? formal) #t (if (identifie",
|
|
"r? formal) #t (if (pair? formal) (if (identifier? (car formal)) (check-formal (c",
|
|
"dr formal)) #f) #f))))) (builtin:define-macro lambda (builtin:lambda (form env) ",
|
|
"(if (= (length form) 1) (error \"illegal lambda form\" form) (if (check-formal (ca",
|
|
"dr form)) (list the-builtin-lambda (cadr form) (cons the-begin (cddr form))) (er",
|
|
"ror \"illegal lambda form\" form))))) (builtin:define-macro define (lambda (form e",
|
|
"nv) ((lambda (len) (if (= len 1) (error \"illegal define form\" form) (if (identif",
|
|
"ier? (cadr form)) (if (= len 3) (cons the-builtin-define (cdr form)) (error \"ill",
|
|
"egal define form\" form)) (if (pair? (cadr form)) (list the-define (car (cadr for",
|
|
"m)) (cons the-lambda (cons (cdr (cadr form)) (cddr form)))) (error \"define: bind",
|
|
"ing to non-varaible object\" form))))) (length form)))) (builtin:define-macro def",
|
|
"ine-macro (lambda (form env) (if (= (length form) 3) (if (identifier? (cadr form",
|
|
")) (cons the-builtin-define-macro (cdr form)) (error \"define-macro: binding to n",
|
|
"on-variable object\" form)) (error \"illegal define-macro form\" form)))) (define-m",
|
|
"acro syntax-error (lambda (form _) (apply error (cdr form)))) (define-macro defi",
|
|
"ne-auxiliary-syntax (lambda (form _) (define message (string-append \"invalid use",
|
|
" of auxiliary syntax: '\" (symbol->string (cadr form)) \"'\")) (list the-define-mac",
|
|
"ro (cadr form) (list the-lambda '_ (list (the 'error) message))))) (define-auxil",
|
|
"iary-syntax else) (define-auxiliary-syntax =>) (define-auxiliary-syntax unquote)",
|
|
" (define-auxiliary-syntax unquote-splicing) (define-auxiliary-syntax syntax-unqu",
|
|
"ote) (define-auxiliary-syntax syntax-unquote-splicing) (define-macro let (lambda",
|
|
" (form env) (if (identifier? (cadr form)) (list (list the-lambda '() (list the-d",
|
|
"efine (cadr form) (cons the-lambda (cons (map car (car (cddr form))) (cdr (cddr ",
|
|
"form))))) (cons (cadr form) (map cadr (car (cddr form)))))) (cons (cons the-lamb",
|
|
"da (cons (map car (cadr form)) (cddr form))) (map cadr (cadr form)))))) (define-",
|
|
"macro and (lambda (form env) (if (null? (cdr form)) #t (if (null? (cddr form)) (",
|
|
"cadr form) (list the-if (cadr form) (cons (the 'and) (cddr form)) #f))))) (defin",
|
|
"e-macro or (lambda (form env) (if (null? (cdr form)) #f (let ((tmp (make-identif",
|
|
"ier 'it env))) (list (the 'let) (list (list tmp (cadr form))) (list the-if tmp t",
|
|
"mp (cons (the 'or) (cddr form)))))))) (define-macro cond (lambda (form env) (let",
|
|
" ((clauses (cdr form))) (if (null? clauses) #undefined (let ((clause (car clause",
|
|
"s))) (if (and (identifier? (car clause)) (identifier=? (the 'else) (make-identif",
|
|
"ier (car clause) env))) (cons the-begin (cdr clause)) (if (null? (cdr clause)) (",
|
|
"let ((tmp (make-identifier 'tmp here))) (list (the 'let) (list (list tmp (car cl",
|
|
"ause))) (list the-if tmp tmp (cons (the 'cond) (cdr clauses))))) (if (and (ident",
|
|
"ifier? (cadr clause)) (identifier=? (the '=>) (make-identifier (cadr clause) env",
|
|
"))) (let ((tmp (make-identifier 'tmp here))) (list (the 'let) (list (list tmp (c",
|
|
"ar clause))) (list the-if tmp (list (car (cddr clause)) tmp) (cons (the 'cond) (",
|
|
"cdr clauses))))) (list the-if (car clause) (cons the-begin (cdr clause)) (cons (",
|
|
"the 'cond) (cdr clauses))))))))))) (define-macro quasiquote (lambda (form env) (",
|
|
"define (quasiquote? form) (and (pair? form) (identifier? (car form)) (identifier",
|
|
"=? (the 'quasiquote) (make-identifier (car form) env)))) (define (unquote? form)",
|
|
" (and (pair? form) (identifier? (car form)) (identifier=? (the 'unquote) (make-i",
|
|
"dentifier (car form) env)))) (define (unquote-splicing? form) (and (pair? form) ",
|
|
"(pair? (car form)) (identifier? (caar form)) (identifier=? (the 'unquote-splicin",
|
|
"g) (make-identifier (caar form) env)))) (define (qq depth expr) (cond ((unquote?",
|
|
" expr) (if (= depth 1) (car (cdr expr)) (list (the 'list) (list (the 'quote) (th",
|
|
"e 'unquote)) (qq (- depth 1) (car (cdr expr)))))) ((unquote-splicing? expr) (if ",
|
|
"(= depth 1) (list (the 'append) (car (cdr (car expr))) (qq depth (cdr expr))) (l",
|
|
"ist (the 'cons) (list (the 'list) (list (the 'quote) (the 'unquote-splicing)) (q",
|
|
"q (- depth 1) (car (cdr (car expr))))) (qq depth (cdr expr))))) ((quasiquote? ex",
|
|
"pr) (list (the 'list) (list (the 'quote) (the 'quasiquote)) (qq (+ depth 1) (car",
|
|
" (cdr expr))))) ((pair? expr) (list (the 'cons) (qq depth (car expr)) (qq depth ",
|
|
"(cdr expr)))) ((vector? expr) (list (the 'list->vector) (qq depth (vector->list ",
|
|
"expr)))) (else (list (the 'quote) expr)))) (let ((x (cadr form))) (qq 1 x)))) (d",
|
|
"efine-macro let* (lambda (form env) (let ((bindings (car (cdr form))) (body (cdr",
|
|
" (cdr form)))) (if (null? bindings) `(,(the 'let) () ,@body) `(,(the 'let) ((,(c",
|
|
"ar (car bindings)) ,@(cdr (car bindings)))) (,(the 'let*) (,@(cdr bindings)) ,@b",
|
|
"ody)))))) (define-macro letrec (lambda (form env) `(,(the 'letrec*) ,@(cdr form)",
|
|
"))) (define-macro letrec* (lambda (form env) (let ((bindings (car (cdr form))) (",
|
|
"body (cdr (cdr form)))) (let ((variables (map (lambda (v) `(,v #f)) (map car bin",
|
|
"dings))) (initials (map (lambda (v) `(,(the 'set!) ,@v)) bindings))) `(,(the 'le",
|
|
"t) (,@variables) ,@initials ,@body))))) (define-macro let-values (lambda (form e",
|
|
"nv) `(,(the 'let*-values) ,@(cdr form)))) (define-macro let*-values (lambda (for",
|
|
"m env) (let ((formal (car (cdr form))) (body (cdr (cdr form)))) (if (null? forma",
|
|
"l) `(,(the 'let) () ,@body) `(,(the 'call-with-values) (,the-lambda () ,@(cdr (c",
|
|
"ar formal))) (,(the 'lambda) (,@(car (car formal))) (,(the 'let*-values) (,@(cdr",
|
|
" formal)) ,@body))))))) (define-macro define-values (lambda (form env) (let ((fo",
|
|
"rmal (car (cdr form))) (body (cdr (cdr form)))) (let ((arguments (make-identifie",
|
|
"r 'arguments here))) `(,the-begin ,@(let loop ((formal formal)) (if (pair? forma",
|
|
"l) `((,the-define ,(car formal) #undefined) ,@(loop (cdr formal))) (if (identifi",
|
|
"er? formal) `((,the-define ,formal #undefined)) '()))) (,(the 'call-with-values)",
|
|
" (,the-lambda () ,@body) (,the-lambda ,arguments ,@(let loop ((formal formal) (a",
|
|
"rgs arguments)) (if (pair? formal) `((,the-set! ,(car formal) (,(the 'car) ,args",
|
|
")) ,@(loop (cdr formal) `(,(the 'cdr) ,args))) (if (identifier? formal) `((,the-",
|
|
"set! ,formal ,args)) '())))))))))) (define-macro do (lambda (form env) (let ((bi",
|
|
"ndings (car (cdr form))) (test (car (car (cdr (cdr form))))) (cleanup (cdr (car ",
|
|
"(cdr (cdr form))))) (body (cdr (cdr (cdr form))))) (let ((loop (make-identifier ",
|
|
"'loop here))) `(,(the 'let) ,loop ,(map (lambda (x) `(,(car x) ,(cadr x))) bindi",
|
|
"ngs) (,the-if ,test (,the-begin ,@cleanup) (,the-begin ,@body (,loop ,@(map (lam",
|
|
"bda (x) (if (null? (cdr (cdr x))) (car x) (car (cdr (cdr x))))) bindings))))))))",
|
|
") (define-macro when (lambda (form env) (let ((test (car (cdr form))) (body (cdr",
|
|
" (cdr form)))) `(,the-if ,test (,the-begin ,@body) #undefined)))) (define-macro ",
|
|
"unless (lambda (form env) (let ((test (car (cdr form))) (body (cdr (cdr form))))",
|
|
" `(,the-if ,test #undefined (,the-begin ,@body))))) (define-macro case (lambda (",
|
|
"form env) (let ((key (car (cdr form))) (clauses (cdr (cdr form)))) (let ((the-ke",
|
|
"y (make-identifier 'key here))) `(,(the 'let) ((,the-key ,key)) ,(let loop ((cla",
|
|
"uses clauses)) (if (null? clauses) #undefined (let ((clause (car clauses))) `(,t",
|
|
"he-if ,(if (and (identifier? (car clause)) (identifier=? (the 'else) (make-ident",
|
|
"ifier (car clause) env))) #t `(,(the 'or) ,@(map (lambda (x) `(,(the 'eqv?) ,the",
|
|
"-key (,the-quote ,x))) (car clause)))) ,(if (and (identifier? (cadr clause)) (id",
|
|
"entifier=? (the '=>) (make-identifier (cadr clause) env))) `(,(car (cdr (cdr cla",
|
|
"use))) ,the-key) `(,the-begin ,@(cdr clause))) ,(loop (cdr clauses))))))))))) (d",
|
|
"efine-macro parameterize (lambda (form env) (let ((formal (car (cdr form))) (bod",
|
|
"y (cdr (cdr form)))) `(,(the 'with-dynamic-environment) (,(the 'list) ,@(map (la",
|
|
"mbda (x) `(,(the 'cons) ,(car x) ,(cadr x))) formal)) (,the-lambda () ,@body))))",
|
|
") (define-macro syntax-quote (lambda (form env) (let ((renames '())) (letrec ((r",
|
|
"ename (lambda (var) (let ((x (assq var renames))) (if x (cadr x) (begin (set! re",
|
|
"names `((,var ,(make-identifier var env) (,(the 'make-identifier) ',var ',env)) ",
|
|
"unquote renames)) (rename var)))))) (walk (lambda (f form) (cond ((identifier? f",
|
|
"orm) (f form)) ((pair? form) `(,(the 'cons) (walk f (car form)) (walk f (cdr for",
|
|
"m)))) ((vector? form) `(,(the 'list->vector) (walk f (vector->list form)))) (els",
|
|
"e `(,(the 'quote) ,form)))))) (let ((form (walk rename (cadr form)))) `(,(the 'l",
|
|
"et) ,(map cdr renames) ,form)))))) (define-macro syntax-quasiquote (lambda (form",
|
|
" env) (let ((renames '())) (letrec ((rename (lambda (var) (let ((x (assq var ren",
|
|
"ames))) (if x (cadr x) (begin (set! renames `((,var ,(make-identifier var env) (",
|
|
",(the 'make-identifier) ',var ',env)) unquote renames)) (rename var))))))) (defi",
|
|
"ne (syntax-quasiquote? form) (and (pair? form) (identifier? (car form)) (identif",
|
|
"ier=? (the 'syntax-quasiquote) (make-identifier (car form) env)))) (define (synt",
|
|
"ax-unquote? form) (and (pair? form) (identifier? (car form)) (identifier=? (the ",
|
|
"'syntax-unquote) (make-identifier (car form) env)))) (define (syntax-unquote-spl",
|
|
"icing? form) (and (pair? form) (pair? (car form)) (identifier? (caar form)) (ide",
|
|
"ntifier=? (the 'syntax-unquote-splicing) (make-identifier (caar form) env)))) (d",
|
|
"efine (qq depth expr) (cond ((syntax-unquote? expr) (if (= depth 1) (car (cdr ex",
|
|
"pr)) (list (the 'list) (list (the 'quote) (the 'syntax-unquote)) (qq (- depth 1)",
|
|
" (car (cdr expr)))))) ((syntax-unquote-splicing? expr) (if (= depth 1) (list (th",
|
|
"e 'append) (car (cdr (car expr))) (qq depth (cdr expr))) (list (the 'cons) (list",
|
|
" (the 'list) (list (the 'quote) (the 'syntax-unquote-splicing)) (qq (- depth 1) ",
|
|
"(car (cdr (car expr))))) (qq depth (cdr expr))))) ((syntax-quasiquote? expr) (li",
|
|
"st (the 'list) (list (the 'quote) (the 'quasiquote)) (qq (+ depth 1) (car (cdr e",
|
|
"xpr))))) ((pair? expr) (list (the 'cons) (qq depth (car expr)) (qq depth (cdr ex",
|
|
"pr)))) ((vector? expr) (list (the 'list->vector) (qq depth (vector->list expr)))",
|
|
") ((identifier? expr) (rename expr)) (else (list (the 'quote) expr)))) (let ((bo",
|
|
"dy (qq 1 (cadr form)))) `(,(the 'let) ,(map cdr renames) ,body)))))) (define (tr",
|
|
"ansformer f) (lambda (form env) (let ((ephemeron1 (make-ephemeron-table)) (ephem",
|
|
"eron2 (make-ephemeron-table))) (letrec ((wrap (lambda (var1) (let ((var2 (epheme",
|
|
"ron1 var1))) (if var2 (cdr var2) (let ((var2 (make-identifier var1 env))) (ephem",
|
|
"eron1 var1 var2) (ephemeron2 var2 var1) var2))))) (unwrap (lambda (var2) (let ((",
|
|
"var1 (ephemeron2 var2))) (if var1 (cdr var1) var2)))) (walk (lambda (f form) (co",
|
|
"nd ((identifier? form) (f form)) ((pair? form) (cons (walk f (car form)) (walk f",
|
|
" (cdr form)))) ((vector? form) (list->vector (walk f (vector->list form)))) (els",
|
|
"e form))))) (let ((form (cdr form))) (walk unwrap (apply f (walk wrap form))))))",
|
|
")) (define-macro define-syntax (lambda (form env) (let ((formal (car (cdr form))",
|
|
") (body (cdr (cdr form)))) (if (pair? formal) `(,(the 'define-syntax) ,(car form",
|
|
"al) (,the-lambda ,(cdr formal) ,@body)) `(,the-define-macro ,formal (,(the 'tran",
|
|
"sformer) (,the-begin ,@body))))))) (define-macro letrec-syntax (lambda (form env",
|
|
") (let ((formal (car (cdr form))) (body (cdr (cdr form)))) `(let () ,@(map (lamb",
|
|
"da (x) `(,(the 'define-syntax) ,(car x) ,(cadr x))) formal) ,@body)))) (define-m",
|
|
"acro let-syntax (lambda (form env) `(,(the 'letrec-syntax) ,@(cdr form)))) (defi",
|
|
"ne (mangle name) (when (null? name) (error \"library name should be a list of at ",
|
|
"least one symbols\" name)) (define (->string n) (cond ((symbol? n) (let ((str (sy",
|
|
"mbol->string n))) (string-for-each (lambda (c) (when (or (char=? c #\\.) (char=? ",
|
|
"c #\\/)) (error \"elements of library name may not contain '.' or '/'\" n))) str) s",
|
|
"tr)) ((and (number? n) (exact? n)) (number->string n)) (else (error \"symbol or i",
|
|
"nteger is required\" n)))) (define (join strs delim) (let loop ((res (car strs)) ",
|
|
"(strs (cdr strs))) (if (null? strs) res (loop (string-append res delim (car strs",
|
|
")) (cdr strs))))) (join (map ->string name) \".\")) (define-macro define-library (",
|
|
"lambda (form _) (let ((lib (mangle (cadr form))) (body (cddr form))) (or (find-l",
|
|
"ibrary lib) (make-library lib)) (for-each (lambda (expr) (eval expr lib)) body))",
|
|
")) (define-macro cond-expand (lambda (form _) (letrec ((test (lambda (form) (or ",
|
|
"(eq? form 'else) (and (symbol? form) (memq form (features))) (and (pair? form) (",
|
|
"case (car form) ((library) (find-library (mangle (cadr form)))) ((not) (not (tes",
|
|
"t (cadr form)))) ((and) (let loop ((form (cdr form))) (or (null? form) (and (tes",
|
|
"t (car form)) (loop (cdr form)))))) ((or) (let loop ((form (cdr form))) (and (pa",
|
|
"ir? form) (or (test (car form)) (loop (cdr form)))))) (else #f))))))) (let loop ",
|
|
"((clauses (cdr form))) (if (null? clauses) #undefined (if (test (caar clauses)) ",
|
|
"`(,the-begin ,@(cdar clauses)) (loop (cdr clauses)))))))) (define-macro import (",
|
|
"lambda (form _) (let ((caddr (lambda (x) (car (cdr (cdr x))))) (prefix (lambda (",
|
|
"prefix symbol) (string->symbol (string-append (symbol->string prefix) (symbol->s",
|
|
"tring symbol))))) (getlib (lambda (name) (let ((lib (mangle name))) (if (find-li",
|
|
"brary lib) lib (error \"library not found\" name)))))) (letrec ((extract (lambda (",
|
|
"spec) (case (car spec) ((only rename prefix except) (extract (cadr spec))) (else",
|
|
" (getlib spec))))) (collect (lambda (spec) (case (car spec) ((only) (let ((alist",
|
|
" (collect (cadr spec)))) (map (lambda (var) (assq var alist)) (cddr spec)))) ((r",
|
|
"ename) (let ((alist (collect (cadr spec))) (renames (map (lambda (x) `((car x) c",
|
|
"adr x)) (cddr spec)))) (map (lambda (s) (or (assq (car s) renames) s)) alist))) ",
|
|
"((prefix) (let ((alist (collect (cadr spec)))) (map (lambda (s) (cons (prefix (c",
|
|
"addr spec) (car s)) (cdr s))) alist))) ((except) (let ((alist (collect (cadr spe",
|
|
"c)))) (let loop ((alist alist)) (if (null? alist) '() (if (memq (caar alist) (cd",
|
|
"dr spec)) (loop (cdr alist)) (cons (car alist) (loop (cdr alist)))))))) (else (m",
|
|
"ap (lambda (x) (cons x x)) (library-exports (getlib spec)))))))) (letrec ((impor",
|
|
"t (lambda (spec) (let ((lib (extract spec)) (alist (collect spec))) (for-each (l",
|
|
"ambda (slot) (library-import lib (cdr slot) (car slot))) alist))))) (for-each im",
|
|
"port (cdr form))))))) (define-macro export (lambda (form _) (letrec ((collect (l",
|
|
"ambda (spec) (cond ((symbol? spec) `(,spec unquote spec)) ((and (list? spec) (= ",
|
|
"(length spec) 3) (eq? (car spec) 'rename)) `(,(list-ref spec 1) unquote (list-re",
|
|
"f spec 2))) (else (error \"malformed export\"))))) (export (lambda (spec) (let ((s",
|
|
"lot (collect spec))) (library-export (car slot) (cdr slot)))))) (for-each export",
|
|
" (cdr form))))) (export define lambda quote set! if begin define-macro let let* ",
|
|
"letrec letrec* let-values let*-values define-values quasiquote unquote unquote-s",
|
|
"plicing and or cond case else => do when unless parameterize define-syntax synta",
|
|
"x-quote syntax-unquote syntax-quasiquote syntax-unquote-splicing let-syntax letr",
|
|
"ec-syntax syntax-error) ",
|
|
};
|
|
|
|
void
|
|
pic_boot(pic_state *pic)
|
|
{
|
|
pic_load_cstr(pic, &boot_rom[0][0]);
|
|
}
|