At Fri, 13 Sep 2013 17:21:09 +0400, Dmitry Pavlov wrote: > > You have a reader for your language that is triggered by "#lang", > > right? > > > > Is that reader in a `reader` submodule, or is it in a separate > > ".../lang/reader.rkt" module file? > > In a separate file: > > $ cat lang/reader.rkt > (module reader syntax/module-reader > #:language 'slon/slon-language > #:read slon-read > #:read-syntax slon-read-syntax > #:whole-body-readers? #t > #:language-info '#(slon/lang/lang-info get-info #f) > #:info (lambda (key defval default) > (case key > ((color-lexer) > (dynamic-require 'slon/tool/syntax-color 'get-syntax-token)) > (else (default key defval)))) > (require slon/slon-parser)) > > > I believe I used that approach before submodules appeared > in Racket... why does it matter anyway?
Assuming that this module is `slon/lang/reader`, does it help to add ++lib slon/lang/reader to the `raco exe` command, along with the `++lib` argument that you have already? (I think that `raco exe` should probably have a `++lang` option that can tracks down the reader module for you.) > > At Fri, 13 Sep 2013 17:01:36 +0400, Dmitry Pavlov wrote: > >> Matthew, > >> > >> Many thanks! Your code works perfectly for my program. > >> > >> Now I would like to describe my tries to make a standalone > >> executable out of my program. > >> > >> Most obvious way fails: > >> > >> $ raco exe slon-main.rkt > >> $ ./slon-main > >> standard-module-name-resolver: collection not found > >> collection: "slon" > >> in collection directories: > >> context...: > >> standard-module-name-resolver > >> > >> Not surprising, as the "slon" collection is not mentioned > >> in the slon-main.rkt itself, but is required dynamically. > >> > >> So my second thought was that maybe ++lib would help. > >> It did not. (Did I use the flag incorrectly?) > >> > >> $ raco exe ++lib slon/slon-language slon-main.rkt > >> $ ./slon-main > >> <same error message> > >> > >> > >> Seeking for the solution, I upgraded from raco to the Racket level: > >> > >> #lang racket > >> (require compiler/embed) > >> > >> (create-embedding-executable "slon-main" > >> #:modules '((#f slon/slon-main) (#f slon/slon-language)) > >> #:literal-expression > >> (parameterize ([current-namespace (make-base-namespace)]) > >> (compile `(namespace-require 'slon/slon-main))) > >> #:configure-via-first-module? #t > >> #:verbose? #t) > >> > >> That worked great. "slon-main" was able to run independently > >> of its own location in the file system, and indenendeltly > >> of the presence of the original files in the slon/ collection > >> on disk. > >> > >> But there was another thing. In my implementation, I have > >> some binary data files that are loaded via > >> > >> (define-runtime-path eop.era "../eop/eop.era") > >> > >> The resulting program depended on those files. When I renamed > >> one of them, I got an error message: > >> > >> $ ./slon-main > >> with-input-from-file: cannot open input file > >> path: /home/dpavlov/era/slon/../eop/eop.era > >> > >> > >> "OK", I thought, "raco distribute is supposed to fix that". > >> > >> > >> $ raco distribute slon-distr slon-main > >> $ ls ./slon-distr/lib/plt/slon-main/exts/ert/home/dpavlov/era/eop/ > >> eop.era > >> $ ./slon-distr/bin/slon-main > >> standard-module-name-resolver: collection not found > >> collection: "slon" > >> in collection directories: > >> /home/dpavlov/.racket/5.3.4/collects > >> /home/dpavlov/era/slon/slon-distr/lib/plt/slon-main/collects > >> > >> The executable "slon-main" produced by raco distrubute is > >> different from the original one (although the size is the same). > >> I guess, raco distribute have eliminated the dependency of the > >> binary files with absolute paths, but it reintroduced the > >> dependency on the "slon" collection, which I previously got > >> rid of with the help of (create-embedding-executable)! > >> > >> And here I am stuck, asking for help. > >> > >> > >> Regards, > >> > >> Dmitry > >> > >> > >> > >> > >> On 09/13/2013 05:33 AM, Matthew Flatt wrote: > >>> I'm not sure I understand what you want, but here are some ideas about > >>> evaluating a text that would a module if only a "#lang" line were > >>> added. > >>> > >>> To start, here's a function to `require` an input port that contains a > >>> module's source. It uses the current namespace, and it gensyms a name > >>> for the module if you don't provide one. The part that I think is least > >>> obvious is using `current-module-declare-name` to set the name of the > >>> module to that it can be found by `dynamic-require`: > >>> > >>> (require syntax/modread) > >>> > >>> (define (require-input-port p [name (gensym)]) > >>> (define module-name (make-resolved-module-path name)) > >>> (parameterize ([current-module-declare-name module-name]) > >>> (eval-syntax (check-module-form ; ensures that `module` is bound > >>> (with-module-reading-parameterization > >>> (lambda () > >>> (read-syntax (object-name p) p))) > >>> 'ignored > >>> #f))) > >>> (dynamic-require module-name #f)) > >>> > >>> The `require-input-port` function assumes that the source starts with > >>> "#lang". You could use `input-port-append`, as others have suggested, > >>> to add a "#lang" line: > >>> > >>> (define p (input-port-append #t > >>> (open-input-string "#lang racket/base\n") > >>> (open-input-file "body.rktd"))) > >>> (port-count-lines! p) > >>> (require-input-port p) > >>> > >>> A problem with `input-port-append` is that line numbers are off by one > >>> for error reporting, and positions are off by the length of the first > >>> line. That's an annoyingly difficult problem to fix, but > >>> `prefix-input-port` below is my attempt (and maybe `input-port-append` > >>> should just work better along similar lines). > >>> > >>> (define p (prefix-input-port #"#lang racket/base\n" > >>> (open-input-file "body.rktd"))) > >>> (port-count-lines! p) > >>> (require-input-port p) > >>> > >>> ---------------------------------------- > >>> > >>> ;; prefix-input-port : bytes input-port -> input-port > >>> ;; Directs position requests to the given port after the > >>> ;; prefix is read. > >>> ;; Closes the given input port when the result port is closed. > >>> (define (prefix-input-port prefix base-p) > >>> (define-values (prefix-i prefix-o) (make-pipe)) > >>> (write-bytes prefix prefix-o) > >>> (close-output-port prefix-o) > >>> (define (prefix-done?) > >>> (zero? (pipe-content-length prefix-i))) > >>> > >>> (make-input-port > >>> (object-name base-p) > >>> ;; read > >>> (lambda (bstr) > >>> (define n (read-bytes-avail!* bstr > >>> (if (prefix-done?) > >>> base-p > >>> prefix-i))) > >>> (if (equal? n 0) > >>> (wrap-evt base-p (lambda (v) 0)) > >>> n)) > >>> ;; peek > >>> (lambda (bstr offset evt) > >>> (define pre-n (pipe-content-length prefix-i)) > >>> (define n (if (offset . >= . pre-n) > >>> (peek-bytes-avail!* bstr > >>> (- offset pre-n) > >>> #f > >>> base-p) > >>> (peek-bytes-avail!* bstr > >>> offset > >>> #f > >>> prefix-i))) > >>> (if (equal? n 0) > >>> (wrap-evt base-p (lambda (v) 0)) > >>> n)) > >>> ;; close > >>> (lambda () > >>> (close-input-port base-p)) > >>> ;; get-progress-evt > >>> ;; Difficult (impossible?) to support at the > >>> ;; prefix--base boundary. > >>> #f > >>> ;; commit > >>> #f > >>> ;; get-location > >>> (lambda () > >>> (if (prefix-done?) > >>> (port-next-location base-p) > >>> (port-next-location prefix-i))) > >>> ;; count-lines! > >>> (lambda () > >>> (port-count-lines! prefix-i) > >>> (port-count-lines! base-p)))) > >>> > >>> > >>> > > > > ____________________ Racket Users list: http://lists.racket-lang.org/users