;;;; 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 . ;;;; ;;; 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)))