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)))) (if (null? formal) `(,the-begin ,@body) (let ((bind (car fo",
|
|
"rmal))) `(,(the 'dynamic-bind) ,(car bind) ,(cadr bind) (,the-lambda () (,(the '",
|
|
"parameterize) ,(cdr formal) ,@body)))))))) (define-macro syntax-quote (lambda (f",
|
|
"orm env) (let ((renames '())) (letrec ((rename (lambda (var) (let ((x (assq var ",
|
|
"renames))) (if x (cadr x) (begin (set! renames `((,var ,(make-identifier var env",
|
|
") (,(the 'make-identifier) ',var ',env)) unquote renames)) (rename var)))))) (wa",
|
|
"lk (lambda (f form) (cond ((identifier? form) (f form)) ((pair? form) `(,(the 'c",
|
|
"ons) (walk f (car form)) (walk f (cdr form)))) ((vector? form) `(,(the 'list->ve",
|
|
"ctor) (walk f (vector->list form)))) (else `(,(the 'quote) ,form)))))) (let ((fo",
|
|
"rm (walk rename (cadr form)))) `(,(the 'let) ,(map cdr renames) ,form)))))) (def",
|
|
"ine-macro syntax-quasiquote (lambda (form env) (let ((renames '())) (letrec ((re",
|
|
"name (lambda (var) (let ((x (assq var renames))) (if x (cadr x) (begin (set! ren",
|
|
"ames `((,var ,(make-identifier var env) (,(the 'make-identifier) ',var ',env)) u",
|
|
"nquote renames)) (rename var))))))) (define (syntax-quasiquote? form) (and (pair",
|
|
"? form) (identifier? (car form)) (identifier=? (the 'syntax-quasiquote) (make-id",
|
|
"entifier (car form) env)))) (define (syntax-unquote? form) (and (pair? form) (id",
|
|
"entifier? (car form)) (identifier=? (the 'syntax-unquote) (make-identifier (car ",
|
|
"form) env)))) (define (syntax-unquote-splicing? form) (and (pair? form) (pair? (",
|
|
"car form)) (identifier? (caar form)) (identifier=? (the 'syntax-unquote-splicing",
|
|
") (make-identifier (caar form) env)))) (define (qq depth expr) (cond ((syntax-un",
|
|
"quote? expr) (if (= depth 1) (car (cdr expr)) (list (the 'list) (list (the 'quot",
|
|
"e) (the 'syntax-unquote)) (qq (- depth 1) (car (cdr expr)))))) ((syntax-unquote-",
|
|
"splicing? expr) (if (= depth 1) (list (the 'append) (car (cdr (car expr))) (qq d",
|
|
"epth (cdr expr))) (list (the 'cons) (list (the 'list) (list (the 'quote) (the 's",
|
|
"yntax-unquote-splicing)) (qq (- depth 1) (car (cdr (car expr))))) (qq depth (cdr",
|
|
" expr))))) ((syntax-quasiquote? expr) (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)))) ((identifier? expr) (rename expr)) (e",
|
|
"lse (list (the 'quote) expr)))) (let ((body (qq 1 (cadr form)))) `(,(the 'let) ,",
|
|
"(map cdr renames) ,body)))))) (define (transformer f) (lambda (form env) (let ((",
|
|
"ephemeron1 (make-ephemeron)) (ephemeron2 (make-ephemeron))) (letrec ((wrap (lamb",
|
|
"da (var1) (let ((var2 (ephemeron1 var1))) (if var2 (cdr var2) (let ((var2 (make-",
|
|
"identifier var1 env))) (ephemeron1 var1 var2) (ephemeron2 var2 var1) var2))))) (",
|
|
"unwrap (lambda (var2) (let ((var1 (ephemeron2 var2))) (if var1 (cdr var1) var2))",
|
|
")) (walk (lambda (f form) (cond ((identifier? form) (f form)) ((pair? form) (con",
|
|
"s (walk f (car form)) (walk f (cdr form)))) ((vector? form) (list->vector (walk ",
|
|
"f (vector->list form)))) (else 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) `(,(t",
|
|
"he 'define-syntax) ,(car formal) (,the-lambda ,(cdr formal) ,@body)) `(,the-defi",
|
|
"ne-macro ,formal (,(the 'transformer) (,the-begin ,@body))))))) (define-macro le",
|
|
"trec-syntax (lambda (form env) (let ((formal (car (cdr form))) (body (cdr (cdr f",
|
|
"orm)))) `(let () ,@(map (lambda (x) `(,(the 'define-syntax) ,(car x) ,(cadr x)))",
|
|
" formal) ,@body)))) (define-macro let-syntax (lambda (form env) `(,(the 'letrec-",
|
|
"syntax) ,@(cdr form)))) (define (mangle name) (when (null? name) (error \"library",
|
|
" name should be a list of at least one symbols\" name)) (define (->string n) (con",
|
|
"d ((symbol? n) (let ((str (symbol->string n))) (string-for-each (lambda (c) (whe",
|
|
"n (or (char=? c #\\.) (char=? c #\\/)) (error \"elements of library name may not co",
|
|
"ntain '.' or '/'\" n))) str) str)) ((and (number? n) (exact? n)) (number->string ",
|
|
"n)) (else (error \"symbol or integer is required\" n)))) (define (join strs delim)",
|
|
" (let loop ((res (car strs)) (strs (cdr strs))) (if (null? strs) res (loop (stri",
|
|
"ng-append res delim (car strs)) (cdr strs))))) (join (map ->string name) \".\")) (",
|
|
"define-macro define-library (lambda (form _) (let ((lib (mangle (cadr form))) (b",
|
|
"ody (cddr form))) (or (find-library lib) (make-library lib)) (for-each (lambda (",
|
|
"expr) (eval expr lib)) body)))) (define-macro cond-expand (lambda (form _) (letr",
|
|
"ec ((test (lambda (form) (or (eq? form 'else) (and (symbol? form) (memq form (fe",
|
|
"atures))) (and (pair? form) (case (car form) ((library) (find-library (mangle (c",
|
|
"adr form)))) ((not) (not (test (cadr form)))) ((and) (let loop ((form (cdr form)",
|
|
")) (or (null? form) (and (test (car form)) (loop (cdr form)))))) ((or) (let loop",
|
|
" ((form (cdr form))) (and (pair? form) (or (test (car form)) (loop (cdr form))))",
|
|
")) (else #f))))))) (let loop ((clauses (cdr form))) (if (null? clauses) #undefin",
|
|
"ed (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 (symb",
|
|
"ol->string prefix) (symbol->string symbol))))) (getlib (lambda (name) (let ((lib",
|
|
" (mangle name))) (if (find-library 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 (c",
|
|
"ar spec) ((only) (let ((alist (collect (cadr spec)))) (map (lambda (var) (assq v",
|
|
"ar alist)) (cddr spec)))) ((rename) (let ((alist (collect (cadr spec))) (renames",
|
|
" (map (lambda (x) `((car x) cadr x)) (cddr spec)))) (map (lambda (s) (or (assq (",
|
|
"car s) renames) s)) alist))) ((prefix) (let ((alist (collect (cadr spec)))) (map",
|
|
" (lambda (s) (cons (prefix (caddr spec) (car s)) (cdr s))) alist))) ((except) (l",
|
|
"et ((alist (collect (cadr spec)))) (let loop ((alist alist)) (if (null? alist) '",
|
|
"() (if (memq (caar alist) (cddr spec)) (loop (cdr alist)) (cons (car alist) (loo",
|
|
"p (cdr alist)))))))) (else (map (lambda (x) (cons x x)) (library-exports (getlib",
|
|
" spec)))))))) (letrec ((import (lambda (spec) (let ((lib (extract spec)) (alist ",
|
|
"(collect spec))) (for-each (lambda (slot) (library-import lib (cdr slot) (car sl",
|
|
"ot))) alist))))) (for-each import (cdr form))))))) (define-macro export (lambda ",
|
|
"(form _) (letrec ((collect (lambda (spec) (cond ((symbol? spec) `(,spec unquote ",
|
|
"spec)) ((and (list? spec) (= (length spec) 3) (eq? (car spec) 'rename)) `(,(list",
|
|
"-ref spec 1) unquote (list-ref spec 2))) (else (error \"malformed export\"))))) (e",
|
|
"xport (lambda (spec) (let ((slot (collect spec))) (library-export (car slot) (cd",
|
|
"r 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-splicing and or cond case else => do when unless par",
|
|
"ameterize define-syntax syntax-quote syntax-unquote syntax-quasiquote syntax-unq",
|
|
"uote-splicing let-syntax letrec-syntax syntax-error) ",
|
|
};
|
|
|
|
void
|
|
pic_boot(pic_state *pic)
|
|
{
|
|
pic_load_cstr(pic, &boot_rom[0][0]);
|
|
}
|