rebirth: Add `eval'

* build-aux/bootstrap/rebirth.scm: Provide env to `rebirth->ecmascript-prog'.
  (rebirth->ecmascript-prog)[env-es]: New param.  Use for `_env' in
    generated self-executing ES function.
  (es:empty-env): New procedure.
* build-aux/bootstrap/rebirth/es.scm (es:raw): Remove unused macro.
  (es:envf)[env]: New parameter.  Use in place of hard-coded inherited env.
  (es:inherit-env): New procedure, extracted from proceeding.
  (lambda, let): Use it.
  (null-environment, eval): New procedures.
master
Mike Gerwitz 2018-02-08 23:11:21 -05:00
parent ec43d7717a
commit e8c9c6cdd8
Signed by: mikegerwitz
GPG Key ID: 8C917B7F5DC51BA2
2 changed files with 34 additions and 14 deletions

View File

@ -844,15 +844,20 @@
;; 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)
(define (rebirth->ecmascript-prog ast env-es)
;; (note that we no longer depend on libprebirth)
(string-append "(function(_env){"
(rebirth->ecmascript ast)
"})({macros:{}});"))
"})(" env-es ");"))
;; An empty environment.
(define (es:empty-env)
"{macros:{}}")
;; 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:file->string "/dev/stdin"))
(es:empty-env)))

View File

@ -79,20 +79,18 @@
(define-macro (es:error . args)
(`quote (%es:native-apply console.error (unquote@ args))))
(define-macro (es:raw . body)
(`quote
(string->es (unquote@ body))))
;; Expand the body BODY into a new environment inherited from the current
;; environment. Environments are currently handled by the ES runtime, so
;; this is easy.
(define-macro (es:envf . body)
;; Expand the body BODY into a new environment. Environments are
;; currently handled by the ES runtime, so this is easy.
(define-macro (es:envf env . body)
(`quote
(string-append
"(function(_env){"
"return "
(unquote@ body)
"})(Object.create(_env))")))
"})(" (unquote env) ")")))
(define (es:inherit-env)
"Object.create(_env)")
(define-macro (define-es-macro decl . body)
(quasiquote
@ -116,7 +114,7 @@
"__whilebrk=true")
(define-es-macro (lambda fnargs . body)
(es:envf
(es:envf (es:inherit-env)
"function(" (join ", " (map tparam->es fnargs)) "){\n"
(env-params fnargs)
(body->es body #t)
@ -138,7 +136,7 @@
(fparams (join ", " (map tparam->es params)))
(args (map cadr bindings))
(fargs (map sexp->es args)))
(string-append (es:envf
(string-append (es:envf (es:inherit-env)
"(function(" fparams "){\n"
(env-params params)
(body->es body #t) "\n"
@ -199,6 +197,23 @@
(`quote (let () (unquote@ exprs))))
;; This doesn't currently produce any sort of encapsulated
;; environment---it just produces an ECMAScript string. This also
;; does not provide any of the expected syntatic keywords yet.
(define (null-environment version)
(if (not (eq? version 5))
(error "null-environment version must be 5")
(es:empty-env)))
;; `eval' re-uses the macro `list->ast' procedure, immediately applying
;; its result.
(define-macro (eval expr env)
(`quote (%es:native-apply
eval
(es:envf (unquote env)
(sexp->es (list->ast (unquote expr)))))))
;; We unfortunately have to worry about environment mutability in the
;; current implementation. Since variables within environments are
;; implemented using ECMAScript's prototype chain, any sets affect the