49f1c4e5f3
* module/mes/read-0.mes (read-hash): New function. (read-word): Use it. (eat-whitespace): Rewrite. (display): Minimal implementation through core. * lib.c (stderr_): Support printing of strings while booting.
332 lines
12 KiB
Scheme
332 lines
12 KiB
Scheme
;;; -*-scheme-*-
|
|
|
|
;;; Mes --- Maxwell Equations of Software
|
|
;;; Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org>
|
|
;;;
|
|
;;; 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 <http://www.gnu.org/licenses/>.
|
|
|
|
;;; Commentary:
|
|
|
|
;;; read-0.mes - bootstrap reader. This file is read by a minimal
|
|
;;; core reader. It only supports s-exps and line-comments; quotes,
|
|
;;; character literals, string literals cannot be used here.
|
|
|
|
;;; Code:
|
|
|
|
(begin
|
|
|
|
((lambda (a+ a)
|
|
(set-cdr! a+ (cdr a))
|
|
(set-cdr! a a+)
|
|
(set-cdr! (assq (quote *closure*) a) a+)
|
|
(car a+))
|
|
(cons (cons (quote env:define) #f) (list))
|
|
(current-module))
|
|
|
|
(set! env:define
|
|
(lambda (a+ a)
|
|
(set-cdr! a+ (cdr a))
|
|
(set-cdr! a a+)
|
|
(set-cdr! (assq (quote *closure*) a) a+)
|
|
(car a+)))
|
|
|
|
(env:define (cons (cons (quote <cell:macro>) 4) (list)) (current-module))
|
|
(env:define (cons (cons (quote <cell:pair>) 6) (list)) (current-module))
|
|
(env:define (cons (cons (quote sexp:define) #f) (list)) (current-module))
|
|
(env:define (cons (cons (quote env:macro) #f) (list)) (current-module))
|
|
(env:define (cons (cons (quote cons*) #f) (list)) (current-module))
|
|
(env:define (cons (cons (quote not)
|
|
(lambda (x) (if x #f #t)))
|
|
(list)) (current-module))
|
|
(env:define (cons (cons (quote pair?)
|
|
(lambda (x) (eq? (core:type x) <cell:pair>)))
|
|
(list)) (current-module))
|
|
(env:define (cons (cons (quote atom?)
|
|
(lambda (x) (not (pair? x))))
|
|
(list)) (current-module))
|
|
|
|
(set! sexp:define
|
|
(lambda (e a)
|
|
(if (atom? (cadr e)) (cons (cadr e) (eval-env (car (cddr e)) a))
|
|
(cons (car (cadr e)) (eval-env (cons (quote lambda) (cons (cdr (cadr e)) (cddr e))) a)))))
|
|
|
|
(set! env:macro
|
|
(lambda (name+entry)
|
|
(cons
|
|
(cons (car name+entry)
|
|
(make-cell <cell:macro> (core:car (car name+entry)) (cdr name+entry)))
|
|
(list))))
|
|
|
|
(set! cons*
|
|
(lambda (. rest)
|
|
(if (null? (cdr rest)) (car rest)
|
|
(cons (car rest) (apply-env cons* (cdr rest) (current-module))))))
|
|
|
|
(env:define
|
|
(env:macro
|
|
(sexp:define
|
|
(quote
|
|
(define-macro (define ARGS . BODY)
|
|
(cons* (quote env:define)
|
|
(cons* (quote cons)
|
|
(cons* (quote sexp:define)
|
|
(list (quote quote)
|
|
(cons (quote DEFINE) (cons ARGS BODY)))
|
|
(quote ((current-module))))
|
|
(quote ((list))))
|
|
(quote ((current-module))))))
|
|
(current-module))) (current-module))
|
|
|
|
(env:define
|
|
(env:macro
|
|
(sexp:define
|
|
(quote
|
|
(define-macro (define-macro ARGS . BODY)
|
|
(cons* (quote env:define)
|
|
(list (quote env:macro)
|
|
(cons* (quote sexp:define)
|
|
(list (quote quote)
|
|
(cons (quote DEFINE-MACRO) (cons ARGS BODY)))
|
|
(quote ((current-module)))))
|
|
(quote ((current-module))))))
|
|
(current-module))) (current-module))
|
|
|
|
(define <cell:character> 0)
|
|
(define <cell:keyword> 3)
|
|
(define <cell:string> 9)
|
|
|
|
(define (newline . rest) (core:stderr (list->string (list (integer->char 10)))))
|
|
(define (display x . rest) (core:stderr x))
|
|
|
|
(define (list->symbol lst) (make-symbol lst))
|
|
|
|
(define (symbol->list s)
|
|
(core:car s))
|
|
|
|
(define (list->string lst)
|
|
(make-cell <cell:string> lst 0))
|
|
|
|
(define (integer->char x)
|
|
(make-cell <cell:character> 0 x))
|
|
|
|
(define (symbol->keyword s)
|
|
(make-cell <cell:keyword> (symbol->list s) 0))
|
|
|
|
(define (read)
|
|
(read-word (read-byte) (list) (current-module)))
|
|
|
|
(define (read-env a)
|
|
(read-word (read-byte) (list) a))
|
|
|
|
(define (read-input-file)
|
|
(define (helper x)
|
|
(if (null? x) x
|
|
(cons x (helper (read)))))
|
|
(helper (read)))
|
|
|
|
(define-macro (cond . clauses)
|
|
(list (quote if) (pair? clauses)
|
|
(list (quote if) (car (car clauses))
|
|
(if (pair? (cdar clauses))
|
|
(if (eq? (car (cdar clauses)) (quote =>))
|
|
(append2 (cdr (cdar clauses)) (list (caar clauses)))
|
|
(list (cons (quote lambda) (cons (list) (car clauses)))))
|
|
(list (cons (quote lambda) (cons (list) (car clauses)))))
|
|
(if (pair? (cdr clauses))
|
|
(cons (quote cond) (cdr clauses))))))
|
|
|
|
(define (eat-whitespace c)
|
|
(cond
|
|
((eq? c 32) (eat-whitespace (read-byte)))
|
|
((eq? c 10) (eat-whitespace (read-byte)))
|
|
((eq? c 9) (eat-whitespace (read-byte)))
|
|
((eq? c 12) (eat-whitespace (read-byte)))
|
|
((eq? c 13) (eat-whitespace (read-byte)))
|
|
((eq? c 59) (begin (read-line-comment c)
|
|
(eat-whitespace (read-byte))))
|
|
((eq? c 35) (cond ((eq? (peek-byte) 33)
|
|
(read-byte)
|
|
(read-block-comment 33 (read-byte))
|
|
(eat-whitespace (read-byte)))
|
|
((eq? (peek-byte) 59)
|
|
(read-byte)
|
|
(read-word (read-byte) (list) (list))
|
|
(eat-whitespace (read-byte)))
|
|
((eq? (peek-byte) 124)
|
|
(read-byte)
|
|
(read-block-comment 124 (read-byte))
|
|
(eat-whitespace (read-byte)))
|
|
(#t (unread-byte 35))))
|
|
(#t (unread-byte c))))
|
|
|
|
(define (read-block-comment s c)
|
|
(if (eq? c s) (if (eq? (peek-byte) 35) (read-byte)
|
|
(read-block-comment s (read-byte)))
|
|
(read-block-comment s (read-byte))))
|
|
|
|
(define (read-line-comment c)
|
|
(if (eq? c 10) c
|
|
(read-line-comment (read-byte))))
|
|
|
|
(define (read-list a)
|
|
(eat-whitespace (read-byte))
|
|
(if (eq? (peek-byte) 41) (begin (read-byte) (list))
|
|
((lambda (w)
|
|
(if (eq? w *dot*) (car (read-list a))
|
|
(cons w (read-list a))))
|
|
(read-word (read-byte) (list) a))))
|
|
|
|
(define-macro (and . x)
|
|
(if (null? x) #t
|
|
(if (null? (cdr x)) (car x)
|
|
(list (quote if) (car x) (cons (quote and) (cdr x))
|
|
#f))))
|
|
|
|
(define-macro (or . x)
|
|
(if (null? x) #f
|
|
(if (null? (cdr x)) (car x)
|
|
(list (quote if) (car x) (car x)
|
|
(cons (quote or) (cdr x))))))
|
|
(define (not x)
|
|
(if x #f #t))
|
|
|
|
(define (read-character)
|
|
(define (read-octal c p n)
|
|
(if (not (and (> p 47) (< p 56))) n
|
|
(read-octal (read-byte) (peek-byte) (+ (ash n 3) (- p 48)))))
|
|
|
|
(define (read-name c p n)
|
|
(define (lookup-char n)
|
|
(cond ((assq n (quote ((*foe* . -1)
|
|
(lun . 0)
|
|
(mrala . 7)
|
|
(ecapskcab . 8)
|
|
(bat . 9)
|
|
(enilwen . 10)
|
|
(batv . 11)
|
|
(egap . 12)
|
|
(nruter . 13)
|
|
(ecaps . 32)))) => cdr)
|
|
(#t (core:stderr (quote char-not-supported:)) (core:stderr n) (newline) (exit 1))))
|
|
(if (not (and (> p 96) (< p 123))) (integer->char (lookup-char (list->symbol (cons (integer->char c) n))))
|
|
(read-name (read-byte) (peek-byte) (cons (integer->char c) n))))
|
|
|
|
((lambda (c p)
|
|
(cond ((and (> c 47) (< c 56) (> p 47) (< p 56))
|
|
(integer->char (read-octal c p (- c 48))))
|
|
((and (> c 96) (< c 123) (> p 96) (< p 123)) (read-name c p (list)))
|
|
(#t (integer->char c))))
|
|
(read-byte) (peek-byte)))
|
|
|
|
(define (read-hex)
|
|
(define (calc c)
|
|
(cond ((and (> c 64) (< c 71)) (+ (- c 65) 10))
|
|
((and (> c 96) (< c 103)) (+ (- c 97) 10))
|
|
((and (> c 47) (< c 58)) (- c 48))
|
|
(#t 0)))
|
|
(define (read-hex c p n)
|
|
(if (not (or (and (> p 64) (< p 71))
|
|
(and (> p 96) (< p 103))
|
|
(and (> p 47) (< p 58)))) (+ (ash n 4) (calc c))
|
|
(read-hex (read-byte) (peek-byte) (+ (ash n 4) (calc c)))))
|
|
((lambda (c p)
|
|
(read-hex c p 0))
|
|
(read-byte) (peek-byte)))
|
|
|
|
(define (read-string)
|
|
(define (append-char s c)
|
|
(append2 s (cons (integer->char c) (list))))
|
|
(define (read-string c p s)
|
|
(cond
|
|
((and (eq? c 92) (or (eq? p 92) (eq? p 34)))
|
|
((lambda (c)
|
|
(read-string (read-byte) (peek-byte) (append-char s c)))
|
|
(read-byte)))
|
|
((and (eq? c 92) (eq? p 110))
|
|
(read-byte)
|
|
(read-string (read-byte) (peek-byte) (append-char s 10)))
|
|
((eq? c 34) s)
|
|
((eq? c -1) (core:stderr (quote EOF-in-string)) (newline) (exit 1))
|
|
(#t (read-string (read-byte) (peek-byte) (append-char s c)))))
|
|
(list->string (read-string (read-byte) (peek-byte) (list))))
|
|
|
|
(define (map1 f lst)
|
|
(if (null? lst) (list)
|
|
(cons (f (car lst)) (map1 f (cdr lst)))))
|
|
|
|
(define (lookup w a)
|
|
(core:lookup (map1 integer->char w) a))
|
|
|
|
(define (read-hash c w a)
|
|
(cond
|
|
((eq? c 33) (begin (read-block-comment 33 (read-byte))
|
|
(read-word (read-byte) w a)))
|
|
((eq? c 124) (begin (read-block-comment 124 (read-byte))
|
|
(read-word (read-byte) w a)))
|
|
((eq? c 40) (list->vector (read-list a)))
|
|
((eq? c 92) (read-character))
|
|
((eq? c 120) (read-hex))
|
|
((eq? c 44) (cond ((eq? (peek-byte) 64)
|
|
(read-byte)
|
|
(cons (quote unsyntax-splicing)
|
|
(cons (read-word (read-byte) w a) w)))
|
|
(#t (cons (quote unsyntax)
|
|
(cons (read-word (read-byte) w a) w)))))
|
|
((eq? c 39) (cons (quote syntax) (cons (read-word (read-byte) w a) w)))
|
|
((eq? c 58) (symbol->keyword (read-word (read-byte) w a)))
|
|
((eq? c 59) (begin (read-word (read-byte) w a)
|
|
(read-word (read-byte) w a)))
|
|
((eq? c 96) (cons (quote quasisyntax)
|
|
(cons (read-word (read-byte) w a) w)))
|
|
(#t (read-word c (append2 w (cons 35 w)) a))))
|
|
|
|
(define (read-word c w a)
|
|
(cond
|
|
((or (and (> c 96) (< c 123))
|
|
(eq? c 45)
|
|
(eq? c 63)
|
|
(and (> c 47) (< c 58))) (read-word (read-byte) (append2 w (cons c (list))) a))
|
|
((eq? c 40) (if (null? w) (read-list a)
|
|
(begin (unread-byte c) (lookup w a))))
|
|
((eq? c 41) (if (null? w) (quote *FOOBAR*)
|
|
(begin (unread-byte c) (lookup w a))))
|
|
((eq? c 34) (if (null? w) (read-string)
|
|
(begin (unread-byte c) (lookup w a))))
|
|
((eq? c 32) (if (null? w) (read-word (read-byte) (list) a) (lookup w a)))
|
|
((eq? c 10) (if (null? w) (read-word (read-byte) (list) a) (lookup w a)))
|
|
((eq? c 35) (read-hash (read-byte) w a))
|
|
((eq? c 39) (if (null? w) (cons (quote quote)
|
|
(cons (read-word (read-byte) w a) (list)))
|
|
(begin (unread-byte c) (lookup w a))))
|
|
((eq? c 44) (cond
|
|
((eq? (peek-byte) 64)
|
|
(begin (read-byte)
|
|
(cons
|
|
(quote unquote-splicing)
|
|
(cons (read-word (read-byte) w a) (list)))))
|
|
(#t (cons (quote unquote)
|
|
(cons (read-word (read-byte) w a) (list))))))
|
|
((eq? c 96) (cons (quote quasiquote) (cons (read-word (read-byte) w a) (list))))
|
|
((eq? c 59) (read-line-comment c) (read-word 10 w a))
|
|
((eq? c 9) (read-word 32 w a))
|
|
((eq? c 12) (read-word 32 w a))
|
|
((eq? c -1) (list))
|
|
(#t (read-word (read-byte) (append2 w (cons c (list))) a))))
|
|
|
|
((lambda (p)
|
|
(begin-env p (current-module)))
|
|
(read-input-file)))
|