Я пытаюсь определить новый язык в ракетке, назовем его wibble. Wibble позволит загружать модули, поэтому он должен переводить свои формы в формы, требующие Racket. Но у меня возникают проблемы с требованием работать при использовании в расширении языка. В конечном итоге я отследил свои проблемы до следующего странного поведения.пытается понять необходимость в расширении языка
Вот мой читатель, который переопределяет read
и read-syntax
=== wibble/lang/reader.rkt ===
#lang racket/base
(provide (rename-out (wibble-read read) (wibble-read-syntax read-syntax)))
(define (wibble-read in)
(wibble-read-syntax #f in))
(define (wibble-read-syntax src in)
#`(module #,(module-name src) wibble/lang
#,@(read-all src in)))
(define (module-name src)
(if (path? src)
(let-values (((base name dir?) (split-path src)))
(string->symbol (path->string (path-replace-suffix name #""))))
'anonymous-module))
(define (read-all src in)
(let loop ((all '()))
(let ((obj (read-syntax src in)))
(if (eof-object? obj)
(reverse all)
(loop (cons obj all))))))
и вот мой очень упрощенный языковый модуль, это вводит (require racket/base)
в каждый Wibble модуль
=== wibble/lang.rkt ===
#lang racket/base
(require (for-syntax racket/base))
(provide (rename-out (wibble-module-begin #%module-begin)) #%app #%datum #%top)
(define-syntax wibble-module-begin
(lambda (stx)
(syntax-case stx()
((_ x ...) #`(#%module-begin (require #,(datum->syntax stx 'racket/base)) x ...)))))
С кода выше, этот Wibble код ' работ, то есть ошибок нет
#lang wibble
(cons 1 2)
(cons 3 4)
но следующий
#lang wibble
(cons 1 2)
дает сообщение об ошибке cons: unbound identifier in module in: cons
Действительно, я просто искал объяснения относительно того, что происходит. Я уверен, что эта разница связана с этим из ракеток документации (Ракетка Reference 3.1)
Если одна форма предусмотрена, то она частично разлагается в контекст модуля-начать. Если расширение приводит к #% plain-module-begin, , тогда тело #% plain-module-begin является телом модуля. Если частичное расширение приводит к любой другой примитивной форме, то форма обернута модулем #% - начните с использования лексического контекста модуля body; этот идентификатор должен быть связан начальным импортом модульного пути, , и его расширение должно создать #% plain-module-begin для подачи тела модуля . Наконец, если предоставлено несколько форм, они завернуты в с #% модулем-begin, как в случае, когда одна форма не развернуть до #% plain-module-begin.
, но даже с этим я не понимаю, почему наличие единой формы имеет какое-либо значение, похоже, что это связано со сроками частичного расширения, но я не уверен. Я также не понимаю, почему Racket рассматривает одну форму как особый случай.
Кстати, я могу решить эту проблему с небольшой модификацией к моему читателю
(define (wibble-read-syntax src in)
#`(module #,(module-name src) wibble/lang
#,@(read-all src in) (void)))
жесткого кодирования (void)
формы означает, что у меня всегда есть более одной формы и Eveything работает.
Извините за длинный пост, я просто ищу какое-то представление о том, как это работает.
Ну, я думаю, у вас это есть. Я не уверен, что когда-нибудь приеду на этот ответ. Синтаксис связан с этим. Благодарю. – john