;;;; Hygienic packages for gscm ;;; J. Welsh, November 2017 ;;; Usage: ;; ;; ;; mypkg.scm ;; (lambda (yourpkg) ;; (define square (yourpkg 'square)) ;; (define (foo x) (write x) (newline)) ;; (define (bar x) (square (+ x 1))) ;; (export foo bar)) ;; ;; ;; yourpkg.scm ;; (lambda () ;; (define (square x) (* x x)) ;; (export square)) ;; ;; ;; myprog.scm ;; (define + 'weird-custom-thing) ;; (load "pkg.scm") ;; (define mypkg (load-pkg "mypkg.scm" (load-pkg "yourpkg.scm"))) ;; (import mypkg foo bar) ;; (foo (bar 5)) ;; ;; $ gscm myprog.scm ;; 36 ;; ;; Ideally, "import" would work internally too, but the current compiler has a ;; quirk that prevents macros expanding to internal definitions. (define (load-pkg path . args) ;; The package is closed in the immutable gscm environment (r5rs plus ;; extensions), protecting it from top-level redefinitions. Dependencies can ;; be injected via args. (apply (eval (with-input-from-file path read) (gales-scheme-environment)) args)) (define-syntax import (syntax-rules () ((import pkg sym) (define sym (or (pkg 'sym) (error "import: not found in package" '(pkg sym))))) ((import pkg sym . tail) (begin (import pkg sym) (import pkg . tail))))) (define-syntax export (syntax-rules () ((export sym) (lambda (tmp-1cb5c81c936f8103) (and (eq? tmp-1cb5c81c936f8103 'sym) sym))) ((export sym . tail) (lambda (tmp-1cb5c81c936f8103) (if (eq? tmp-1cb5c81c936f8103 'sym) sym ((export . tail) tmp-1cb5c81c936f8103))))))