Re: [racket-users] Unit tests for a #lang implementation

2017-09-01 Thread Konrad Hinsen
Matthew,

> If you'd like the test namespace and the test-driving module to share
> the instance of the module that defines `document` (so that they'll
> agree on the data structure), you can use `namespace-attach-module` to
> attach the test-driving module's instance to a newly created namespace.

Thanks again for a valuable pointer to the Racket documentation!

This works well for modules that my test module requires directly,
as in your example. I haven't been able to get any useful results
for modules that are required indirectly (i.e. your module "a.rkt"
requiring "c.rkt" and re-providing a struct from there). Depending
on which combination of modules I run namespace-attach-module on,
I either get my initial error or another one:

amespace-attach-module: a different module with the same name is already in the 
destination namespace
;   module name: "/Applications/Racket v6.10/collects/racket/pretty.rkt"

None of my code refers to pretty.rkt.

I think I will simply give up at this point. Compared to depending on
complex stuff that I don't understand, nor want to understand, a
separate testing shell script seems like the lesser evil.

Thanks again,
  Konrad.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Unit tests for a #lang implementation

2017-08-31 Thread Matthew Flatt
At Thu, 31 Aug 2017 11:31:33 +0200, Konrad Hinsen wrote:
> On 25/08/2017 17:03, Konrad Hinsen wrote:
> 
> > That adds the missing piece - thanks a lot! I had seriously 
> > underestimated the complexity of module definitions in Racket.
> 
> A followup mostly for the benefit of those who find this thread in the 
> archives one day.
> 
> Importing a module this way works perfectly, but its utility for testing 
> is very limited. The problem I run into is illustrated by the following 
> symptom:
> 
> raco test: (submod "lang-test.rkt" test)
> document-contexts: contract violation;
>   given value instantiates a different structure type with the same name
>expected: document?
>given: (document (hash "test-context"  ...
> 
> 
> My code defines a structure called "document", which apparently exists 
> in two copies in memory. One is used by the module lang-test.rkt that 
> contains the tests, and the other one is used by the module that was 
> created from the text string. As a consequence, it is impossible to 
> perform any operation on the date from that module.

If you'd like the test namespace and the test-driving module to share
the instance of the module that defines `document` (so that they'll
agree on the data structure), you can use `namespace-attach-module` to
attach the test-driving module's instance to a newly created namespace.

For example, with

 ;; a.rkt:
 #lang racket/base
 (provide (struct-out a))
 (struct a (x))

 ;; b.rkt:
 #lang racket/base
 (require "a.rkt")
 (parameterize ([current-namespace (make-base-namespace)])
   (eval `(require "a.rkt"))
   (a-x (eval `(a 1

then you get an error

 a-x: contract violation;
  given value instantiates a different structure type with the same name
   expected: a?
   given: #

but attaching the original instance of "a.rkt" avoids the error:

 ;; b.rkt, revised:
 #lang racket/base
 (require "a.rkt")
 (define-namespace-anchor here)
 (parameterize ([current-namespace (make-base-namespace)])
   (namespace-attach-module (namespace-anchor->namespace here)
'"a.rkt")
   (eval `(require "a.rkt"))
   (a-x (eval `(a 1

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Unit tests for a #lang implementation

2017-08-31 Thread Konrad Hinsen

On 25/08/2017 17:03, Konrad Hinsen wrote:

That adds the missing piece - thanks a lot! I had seriously 
underestimated the complexity of module definitions in Racket.


A followup mostly for the benefit of those who find this thread in the 
archives one day.


Importing a module this way works perfectly, but its utility for testing 
is very limited. The problem I run into is illustrated by the following 
symptom:


raco test: (submod "lang-test.rkt" test)
document-contexts: contract violation;
 given value instantiates a different structure type with the same name
  expected: document?
  given: (document (hash "test-context"  ...


My code defines a structure called "document", which apparently exists 
in two copies in memory. One is used by the module lang-test.rkt that 
contains the tests, and the other one is used by the module that was 
created from the text string. As a consequence, it is impossible to 
perform any operation on the date from that module.


If all you recover from that module is basic Racket data structures, 
everything works fine.


Konrad.

--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Unit tests for a #lang implementation

2017-08-25 Thread Konrad Hinsen

On 25/08/2017 16:30, Matthew Flatt wrote:

At Fri, 25 Aug 2017 16:04:01 +0200, Konrad Hinsen wrote:

Putting those together, and using `current-namespace` so that both
`eval-syntax` and check-module-form` use the same namespace:


Thanks, that works!

At least to the point of not getting any error message. I can't say if a
module is actually defined.


I should have suggested setting `current-module-declare-name` during
evaluation of the module form, so that you get to pick the name:



That adds the missing piece - thanks a lot! I had seriously 
underestimated the complexity of module definitions in Racket.


Konrad.

--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Unit tests for a #lang implementation

2017-08-25 Thread Matthew Flatt
At Fri, 25 Aug 2017 16:04:01 +0200, Konrad Hinsen wrote:
> > Putting those together, and using `current-namespace` so that both
> > `eval-syntax` and check-module-form` use the same namespace:
> 
> Thanks, that works!
> 
> At least to the point of not getting any error message. I can't say if a 
> module is actually defined. 

I should have suggested setting `current-module-declare-name` during
evaluation of the module form, so that you get to pick the name:

  (parameterize ([current-namespace (make-base-namespace)])
;; Read module as a syntax object:
(define mod-form
  (parameterize ([read-accept-lang #t]
 [read-accept-reader #t])
(read-syntax
 "test-module"
 (open-input-string
  "#lang scribble/base\n@section{Introduction}"

;; Declare the module:
(parameterize ([current-module-declare-name 
;; declare as name 'demo:
(make-resolved-module-path 'demo)])
  (eval mod-form))

;; Access the module with `dynamic-require`, `namespace-require`, etc.:
(dynamic-require ''demo 'doc))

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Unit tests for a #lang implementation

2017-08-25 Thread Konrad Hinsen

Matthias,


Matthew’s response is probably all you want in principle,
but I think that your ‘unit test’ looks like another person’s
‘integration tests’. Both are useful.

Wouldn’t you want to use unit tests to validate the parser
independently of the macros that expand the S-expression
syntax you create with the parser? If you then discover a
failure, it becomes much easier to search for the bug in
either of the two pieces. (I understand that there are many
more pieces but let’s say ‘two’ for now.)


Thanks for your reply!

I guess what I want to do is somewhere in between unit and integration 
tests. I don't really care much about the labels.


I do have unit tests for the low-level implementation details of my 
#lang. They are plain Racket functions with straightforward tests.


What I want to write additional tests for is

 1) The macros that expand the S-expression for my module

 2) Some of the functions used in the expansion, for which
suitable input is difficult to generate without those
macros.

The parser is not my problem - it's borrowed from Scribble and 
presumable tested by someone else :-)


Konrad.

--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Unit tests for a #lang implementation

2017-08-25 Thread Konrad Hinsen

Matthew,


Putting those together, and using `current-namespace` so that both
`eval-syntax` and check-module-form` use the same namespace:


Thanks, that works!

At least to the point of not getting any error message. I can't say if a 
module is actually defined. A plain


  (require 'anonymous-module)

fails ("unknown module"). I tried changing the name by manipulating the 
s-expression returned by read-syntax, but I am never able to instantiate
the module that was presumably defined by eval under that name. Is this 
perhaps one of those 
"your-identifier-is-not-from-the-scope-you-think-it-is" problems?


Konrad.

--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Unit tests for a #lang implementation

2017-08-25 Thread Matthias Felleisen

Konrad, 

Matthew’s response is probably all you want in principle, 
but I think that your ‘unit test’ looks like another person’s
‘integration tests’. Both are useful. 

Wouldn’t you want to use unit tests to validate the parser 
independently of the macros that expand the S-expression 
syntax you create with the parser? If you then discover a
failure, it becomes much easier to search for the bug in 
either of the two pieces. (I understand that there are many
more pieces but let’s say ‘two’ for now.) 

— Matthias






> On Aug 25, 2017, at 9:17 AM, Matthew Flatt  wrote:
> 
> I forgot to explain why this fails:
> 
> At Fri, 25 Aug 2017 14:59:14 +0200, Konrad Hinsen wrote:
>> (eval-syntax
>>  (parameterize ([read-accept-lang #t]
>> [read-accept-reader #t])
>>(read-syntax "test-module"
>> (open-input-string "#lang 
>> scribble/base\n@section[Introduction]")))
>>  (module->namespace 'racket/base))
>> 
>> only says
>> 
>> ; test-module::1: module: unbound identifier;
>> ;  also, no #%app syntax transformer is bound
>> ;   at: module
>> 
>> although both module and %app are defined in racket/base.
> 
> The `eval-syntax` function refrains from adding any scopes to the given
> syntax object before trying to expand it. So, it doesn't add the scope
> for the namespace's top-level bindings (unlike `eval`, which does add
> that scope before trying to expand). That's why `#%app` and `module`
> are not bound when trying to expand the syntax object in the above
> example; the syntax object has no scopes and therefore no bindings.
> 
> The `check-module-form` function adds a suitable scope to the `module`
> binding in the given syntax object. It would work just as well to not
> use `check-module-form` and to use `eval` so that the `module` binding
> is taken from the namespace.
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Unit tests for a #lang implementation

2017-08-25 Thread Matthew Flatt
I forgot to explain why this fails:

At Fri, 25 Aug 2017 14:59:14 +0200, Konrad Hinsen wrote:
> (eval-syntax
>   (parameterize ([read-accept-lang #t]
>  [read-accept-reader #t])
> (read-syntax "test-module"
>  (open-input-string "#lang 
> scribble/base\n@section[Introduction]")))
>   (module->namespace 'racket/base))
> 
> only says
> 
> ; test-module::1: module: unbound identifier;
> ;  also, no #%app syntax transformer is bound
> ;   at: module
> 
> although both module and %app are defined in racket/base.

The `eval-syntax` function refrains from adding any scopes to the given
syntax object before trying to expand it. So, it doesn't add the scope
for the namespace's top-level bindings (unlike `eval`, which does add
that scope before trying to expand). That's why `#%app` and `module`
are not bound when trying to expand the syntax object in the above
example; the syntax object has no scopes and therefore no bindings.

The `check-module-form` function adds a suitable scope to the `module`
binding in the given syntax object. It would work just as well to not
use `check-module-form` and to use `eval` so that the `module` binding
is taken from the namespace.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Unit tests for a #lang implementation

2017-08-25 Thread Matthew Flatt
I'd say that using `eval` or `eval-syntax` is the right idea, but:

 * It's better to use `make-base-namespace` instead of
   `module->namespace`, since `(module->namespace 'racket/base)` gives
   you a namespace for the inside of `racket/base` instead of a
   top-level namespace that has imported `racket/base`.

 * Use `check-module-form` from `syntax/modread` to make the `module`
   identifier in an S-expression module form (from `read-syntax`) is
   bound to the core `module` form.

Putting those together, and using `current-namespace` so that both
`eval-syntax` and check-module-form` use the same namespace:

   (require syntax/modread)

   (parameterize ([current-namespace (make-base-namespace)])
 (eval-syntax
  (check-module-form
   (parameterize ([read-accept-lang #t]
  [read-accept-reader #t])
  (read-syntax
   "test-module"
   (open-input-string
"#lang scribble/base\n@section{Introduction}")))
   'ignored #f)))


At Fri, 25 Aug 2017 14:59:14 +0200, Konrad Hinsen wrote:
> Hi all,
> 
> I have been trying for a while to write proper unit tests for a language 
> implementation I am working on. By "proper" tests I mean tests that are
> run using raco test just like any other tests. Until now, I have a 
> separate shell-script based testing framework that runs scripts written
> in my own #lang, but all too often I forgot to run those tests.
> 
> For a standard s-exp based language, this is not difficult:
> 
> (module+ test
> 
>(module demo lazy
>  (provide foo)
>  (define (foo x) (* 2 x)))
> 
>(require (only-in 'demo foo))
> 
>(check-equal? (force (foo 2)) 4))
> 
> But for a #lang that uses a different reader, I haven't found a working 
> solution yet. Even if I am willing to re-write my examples in s-exp 
> syntax, I run into problems:
> 
> (module+ test
> 
>(module example scribble/base
>  (section "Introduction"))
> 
>(require (only-in 'example doc))
> 
>(check-equal? (force (foo 2)) 4))
> 
> This yields the error message
> 
>module: no #%module-begin binding in the module's language
> 
> Anyway, what I really want is use the #lang's standard syntax. Reading 
> it isn't much of a problem:
> 
> (parameterize ([read-accept-lang #t]
>  [read-accept-reader #t])
> (read-syntax "test-module"
>  (open-input-string "#lang 
> scribble/base\n@section[Introduction]")))
> 
> But then I get a syntax-object for my module, which I need to evaluate 
> somehow. I'd expect eval-syntax to do the job, but...
> 
> (eval-syntax
>   (parameterize ([read-accept-lang #t]
>  [read-accept-reader #t])
> (read-syntax "test-module"
>  (open-input-string "#lang 
> scribble/base\n@section[Introduction]")))
>   (module->namespace 'racket/base))
> 
> only says
> 
> ; test-module::1: module: unbound identifier;
> ;  also, no #%app syntax transformer is bound
> ;   at: module
> 
> although both module and %app are defined in racket/base.
> 
> Any ideas (or pointers to examples) for doing this correctly?
> 
> Thanks in advance,
>Konrad.
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.