ulambda/bootstrap/rebirth.scm

113 lines
4.7 KiB
Scheme
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

;;;; Rebirth Lisp implemented in Birth and Rebirth Lisp (self-hosting)
;;;;
;;;; Copyright (C) 2017, 2018 Mike Gerwitz
;;;;
;;;; This file is part of Ulambda Scheme.
;;;;
;;;; Ulambda Scheme is free software: you can redistribute it and/or modify
;;;; it under the terms of the GNU Affero General Public License as
;;;; published by the Free Software Foundation, either version 3 of the
;;;; License, or (at your option) any later version.
;;;;
;;;; This program 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 Affero General Public License
;;;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;;;
;;; Commentary:
;;; THIS IS TEMPORARY CODE that will be REWRITTEN IN ULAMBDA SCHEME after a
;;; very basic bootstrap is complete. It is retained as an important
;;; artifact for those who wish to build Ulambda Scheme from scratch without
;;; using another version of Ulambda itself. This is called "self-hosting".
;;;
;;; REBIRTH SHOULD NOT BE USED AS A GENERAL-PURPOSE LISP. It is very
;;; narrowly tested and absolutely has bugs or misfeatures that were
;;; explicitly ignored (some of which are explicitly noted).
;;;
;;; This is the compiler for Rebirth Lisp---it builds off of Birth by
;;; first eliminating the need for libprebirth; this allows _all_
;;; development to happen in a Lisp dialect, which liberates the last
;;; remaining process that isn't technically self-hosted. So, Rebirth
;;; completes the raw, self-hosting bootstrapping process.
;;;
;;; To continue with the creepy birthing puns, you can consider libprebirth
;;; to be the umbilical cord. After Birth, it's still attached---here we
;;; cut it.
;;;
;;; Of course, bootstrapping can't end there: we need a fully functioning
;;; Scheme compiler. Rebirth may as well be called Rerebirth, or
;;; Rererebirth, or Re*birth, or Reⁿbirth---it is a recursively self-hosting
;;; compiler. It adds features to itself each time it compiles itself.
;;;
;;; Note that we're dealing with a small subset of Scheme here, so certain
;;; things might be done differently given a proper implementation.
;;;
;;; This started as an exact copy of `birth.scm', modified to introduce
;;; additional features. This is important, since Birth is mostly a 1:1
;;; translation of the Prebirth compiler and needs to stay that way. This
;;; fork allows us to vary as much as we want from the initial
;;; implementation. See the commit history for this file for more
;;; information as to how it evolved (the first commit is the direct copy
;;; before actual code changes).
;;;
;;; This file follows a narrative (from Birth to Reⁿbirth), but it's more of
;;; a choose-your-adventure-book-style narrative: order of certain
;;; definitions unfortunately matters in this simple implementation. For
;;; example, primitive macros (e.g. `if') must be defined before they are
;;; used, so those appear at the top of this file, despite their definitions
;;; not being supported until future passes.
;;;
;;; Code:
;; So, to begin, goto STEP 0! -------------,
;; V
(include "rebirth/es.scm") ;; STEP 2 (start at STEP 0) <--,
(include "rebirth/relibprebirth.scm") ;; STEP 0 (start here) /
(include "rebirth/macro.scm") ;; STEP 1 (then go to STEP 2) -`
;; The runtime is then initialized and we can proceed with defining the
;; compiler.
;;
;; Most of the compiler has been extracted into a separate file so that it
;; can be used by other programs; this is necessary because the macro system
;; uses those definitions, so naturally any program using macros will
;; require that the compiler definitions be imported.
(include "rebirth/compiler.scm")
;; Compile Rebirth Lisp AST into ECMAScript.
;;
;; The AST can be generated with `parse-lisp'.
(define (rebirth->ecmascript ast)
(join "\n\n" (map sexp->es ast)))
;; Compile Rebirth Lisp AST into an ECMAScript program.
;;
;; This compiles the AST into ECMAScript using `rebirth->ecmascript' and
;; then wraps it in a self-executing function to limit scope and create the
;; toplevel environment.
(define (rebirth->ecmascript-prog ast env-es)
;; (note that we no longer depend on libprebirth)
(string-append "(function(_env){"
(rebirth->ecmascript ast)
"})(" env-es ");"))
;; at this point, this program can parse itself and output a CST (sans
;; whitespace)
(es:console (rebirth->ecmascript-prog
(parse-lisp
(es:file->string "/dev/stdin"))
(es:empty-env)))