(module custom-drscheme-language mzscheme
(require (lib "tool.ss" "drscheme")
(lib "mred.ss" "mred")
(lib "class.ss")
(lib "unit.ss")
(lib "etc.ss")
(lib "kw.ss")
(lib "string-constant.ss" "string-constants")
(only (lib "tool.ss" "macro-debugger") language/macro-stepper<%>))
(provide custom-language-level^
custom-language-level@
top-level->module)
(define (top-level->module lang-path terms)
(with-syntax ([name (datum->syntax-object #f (gensym 'program))]
[language (datum->syntax-object #f lang-path)]
[(body ...) (datum->syntax-object #f terms)]
[module-begin (datum->syntax-object #f '#%module-begin)])
(list
#`(module name language (module-begin body ...))
#`(require 'name)
#`(current-namespace (module->namespace ''name)))))
(define-signature custom-language-level^
(simple-language%
custom-language-level
language-level-render-mixin
language-level-capability-mixin
language-level-eval-as-module-mixin
language-level-no-executable-mixin))
(define-syntax (cond-list stx)
(syntax-case stx ()
[(cl [test expr] ...)
(syntax/loc stx
(let* ([the-list null]
[the-list (if test (cons expr the-list) the-list)]
...)
(reverse the-list)))]))
(define-unit custom-language-level@
(import drscheme:tool^)
(export custom-language-level^)
(define/kw (custom-language-level
name module
#:key
[number (string-length name)]
[hierarchy experimental-language-hierarchy]
[summary name]
[url #f]
[reader generic-syntax-reader]
#:body mixins
)
(let* ([default-mixin (drscheme:language:get-default-mixin)]
[custom-mixin (apply compose (reverse mixins))])
(new (custom-mixin (default-mixin simple-language%))
[module module]
[language-position (append (map car hierarchy) (list name))]
[language-numbers (append (map cdr hierarchy) (list number))]
[one-line-summary summary]
[language-url url]
[reader (make-namespace-syntax-reader reader)])))
(define simple-language%
(drscheme:language:module-based-language->language-mixin
(drscheme:language:simple-module-based-language->module-based-language-mixin
drscheme:language:simple-module-based-language%)))
(define (language-level-render-mixin to-sexp show-void?)
(mixin (drscheme:language:language<%>) ()
(super-new)
(define/override (render-value/format value settings port width)
(unless (and (void? value) (not show-void?))
(super render-value/format (to-sexp value) settings port width)))))
(define (language-level-capability-mixin table)
(mixin (drscheme:language:language<%>) ()
(super-new)
(define/augment (capability-value key)
(hash-table-get
table key
(lambda ()
(inner (drscheme:language:get-capability-default key)
capability-value key))))))
(define language-level-no-executable-mixin
(mixin (drscheme:language:language<%>) ()
(super-new)
(inherit get-language-name)
(define/override (create-executable settings parent filename)
(message-box
"Create Executable: Error"
(format "Sorry, ~a does not support creating executables."
(get-language-name))
#f '(ok stop)))))
(define language-level-eval-as-module-mixin
(mixin (drscheme:language:language<%>
drscheme:language:module-based-language<%>) ()
(super-new)
(inherit get-reader get-module)
(define/private (read-all port)
(let* ([reader (get-reader)]
[name (object-name port)])
(let read-rest ([rev-forms null])
(let* ([form (reader name port)])
(if (eof-object? form)
(reverse rev-forms)
(read-rest (cons form rev-forms)))))))
(define/override (front-end/complete-program port settings)
(let* ([terms #f]
[program (gensym 'program)])
(lambda ()
(unless terms
(set! terms
(top-level->module (get-module) (read-all port))))
(if (pair? terms)
(begin0 (car terms) (set! terms (cdr terms)))
eof))))))
(define macro-stepper-mixin
(mixin (drscheme:language:language<%> language/macro-stepper<%>) ()
(super-new)
(define/override (enable-macro-stepper?) #t)))
(define (generic-syntax-reader . args)
(parameterize ([read-accept-reader #t])
(apply read-syntax args)))
(define (make-namespace-syntax-reader reader)
(lambda args
(let ([stx (apply reader args)])
(if (syntax? stx) (namespace-syntax-introduce stx) stx))))
(define experimental-language-hierarchy
(list (cons (string-constant experimental-languages)
1000)))
)
)