> On Jun 29, 2017, at 09:08, Sam Waxman <samwax...@gmail.com> wrote:
> 
> On Thursday, June 29, 2017 at 11:49:49 AM UTC-4, 'John Clements' via 
> users-redirect wrote:
>> Oops forgot to cc: list
>> 
>>> On Jun 29, 2017, at 08:49, John Clements <cleme...@brinckerhoff.org> wrote:
>>> 
>>>> 
>>>> On Jun 29, 2017, at 08:30, Sam Waxman <samwax...@gmail.com> wrote:
>>>> 
>>>> Hey all,
>>>> 
>>>> I've been running into a lot of major roadblocks when it comes to writing 
>>>> good tests for some #langs that I've made, for a number of reasons.
>>>> 
>>>> Ideally, I want a function called
>>>> (check-eq-program? "program1" "program2")
>>>> That will run each program in a fresh module of my #lang, check what gets 
>>>> printed out, and compare them for equality.
>>>> 
>>>> I'm not quite sure how to write a function that creates and runs code in a 
>>>> fresh module though.
>>>> 
>>>> The fresh module is necessary for a number of reasons: If all of the 
>>>> programs worked in the same module, they would occasionally interfere with 
>>>> each other, as the #%module-begin's some of my #langs have initialize some 
>>>> "global variables" that need to be fresh/reinitialized every time a new 
>>>> program runs.
>>>> 
>>>> Some languages also work with continuations, and if they all ran in one 
>>>> module, would alter control flow so that only one program could ever run 
>>>> (they have aborts in odd places).
>>>> 
>>>> Ideally, the tests could be run in #lang racket instead of my own 
>>>> languages, so that the tests wouldn't be part of my language, so it 
>>>> probably makes sense that check-eq-program would have to take in a third 
>>>> argument for the language to use
>>>> 
>>>> (check-eq-program prog1 prog2 lang) Rackunit sadly does not seem to have 
>>>> anything good for these kinds of tests.
>>>> 
>>>> Can anyone offer some guidance on how to write a function like this, or if 
>>>> there's an easier way to go about this?
>>> 
>>> I think this may be a great deal easier than you think… or maybe impossible.
>>> 
>>> Specifically: the basic idea behind racket’s #lang mechanism is that a 
>>> program is known to be in a particular language when it’s written. For this 
>>> reason, your `check-eq-program` form doesn’t make sense, because the 
>>> programs you’re testing will already be written in a fixed language.
>>> 
>>> I’m a bit confused by your terminology when you say “if all of the programs 
>>> worked in the same module"; specifically, a #lang declaration expands into 
>>> a module, so it’s more or less impossible to write a function in a 
>>> different #lang that isn’t in its own module.
>>> 
>>> The easy case: if your two programs are written as modules, and each one 
>>> has an entry point—a (main) function, perhaps—it sounds like it would be 
>>> sufficient simply to parameterize (current-output-port) to capture the 
>>> output and then call the corresponding function. If not, then you could 
>>> potentially use some combination of (make-namespace-anchor) and (eval)… but 
>>> my humble opinion is that in this case … it would be easier simply to 
>>> create a (main) function as a wrapper. 
>>> 
>>> Apologies if what I’m saying doesn’t make sense; I would also encourage you 
>>> to create a small example, to clarify what you’re asking. 
>>> 
>>> John
> 
> Hey, thanks for the response. To clear up what I'm saying a bit,
> 
> Let's say that one of my languages has a global variable called 
> "NumberFuncsDefined", and every time I define a function in my language, it 
> increments by one. I want to check if the two programs
> 
> "(define (f) 1)
> NumberFuncsDefined"
> 
> and
> "(define (g) 2)
> NumberFuncsDefined"
> 
> result in the same thing, so I write
> 
> (check-eq-program 
>    [(define (f) 1) NumberFuncsDefined)]
>    [(define (g) 2) NumberFuncsDefined)])
> 
> I want this to return true, because both programs defined one function, so 
> both programs should return 1 in my language. If they're working in the same 
> module though (instead of two fresh copies of the module), the first program 
> will increment NumberFuncsDefined, then the second program will be in the 
> same module with the same NumberFuncsDefined, it'll increment it, and now 
> NumberFuncsDefined will be 2 instead of one.


Okay, I think I’m getting the picture now. You want to test that your #lang 
works correctly. 

Here’s some code that will help get you into trouble:

#lang racket

(define-namespace-anchor my-ns-anchor)

(define (run-in-mylang module-str binding)
  (parameterize ([read-accept-lang #t]
                 [read-accept-reader #t]
                 [current-namespace (namespace-anchor->namespace
                                     my-ns-anchor)])
    (eval
     (call-with-input-string
     module-str
     (λ (p) (read-syntax 'zz p))))
    (dynamic-require ''anonymous-module 'f)))

(run-in-mylang "#lang racket
(provide (all-defined-out))
(define f 13)" 'f)

For your tests, of course, the #lang racket would be a different language. 
Also, the string #lang mylang could be prepended automatically, or you could 
construct an s-expression and then flatten it out. Up to you.

John Clements



-- 
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.

Reply via email to