How to implement simple dependencies between DrRacket plugins? - plugins

I want to implement 2 DrRacket plugins or tools, where I have a dependency between one tool and the other. Essentially, one tool must have access to a function provided by the other tool. The current code I have is something like:
providing tool:
(provide tool# extra-signature^)
(define-signature extra-signature^ (some-procedure))
(define tool#
(unit
(import drracket:tool^)
(export drracket:tool-exports^ extra-signature^)
(define (phase1) void)
(define (phase2) void)
(define (some-procedure) void)
))
dependent tool:
(require extra-signature)
(provide tool#)
(define tool#
(unit
(import drracket:tool^ extra-signature^)
(export drracket:tool-exports^)
(define (phase1) void)
(define (phase2) void)
(some-procedure)
))
Trying to run DrRacket with above tools gives the error:
Error invoking tool #<path:/Users/...;("dependentTool.rkt")
define-unit-binding: unit argument expects an untagged import with signature extra-signature^, which this usage context does not supply
How can I actually implement such a dependency between DrRacket plugins?

defining some-procedure at the top level of the providing module, alongside tool#, then using require with only-in in the dependent module

Related

Trouble in defining languages using racket

I'm learning racket and as a way to consolidate my knowledge I'm trying to build a library for parser expression grammars (PEG). My intention is to build a language to express PEGs and the module should export a function parser that receives a string and tries to parse it using the grammar defined in the language. However, I'm struggling with building this module using the following read function:
(define (peg-read-syntax path port)
(define grammar (parse port))
(datum->syntax
#f
`(module peg-mod racket
(provide parser
pretty
(all-from-out "tree.rkt"))
(define (parser s)
(peg-parse ,grammar s))
(define (pretty t)
(peg-pretty ,grammar t))))))
and racket returns the following error whenever I try to process a program in #lang peg language:
default-load-handler: expected a `module' declaration, but found something else
Can someone help me with this mistake? The complete project is at the following github repo:
https://github.com/lives-group/peg-parsing

load a module without evaluating its body at top level

I have this file:
#lang racket
(provide install global-var)
(define global-var 'test)
(define (install)
(set! global-var '(aaa)))
(install)
And I start the repl, typing so:
Welcome to Racket v5.3.5.
> (define global-var "test007")
> global-var
"test007"
> (require "test.rkt")
'(install)
> global-var
'test
Is it possible to load only some definitions from the file test.rkt, such that the loading does not change the value of global-var, only if I call myself (install), after I load?
I want to use only the standard racket system, not outside packages that are not installed by default in racket.
The short answer is: probably not. You should think of a racket module as a pre-compiled bundle of code that exports certain functions. Any expressions at the top level (such as the call to 'install' here) are conceptually part of the module's setup; allowing a user to use the definitions without running the setup code would invalidate the assumptions of the module writer---not nice for the writer of the module.
To take an example, I have a sound library; requiring the sound library module initializes the sound playback. If there were a tricky way to load the module without running this code, my invariants would be violated.
Perhaps you can explain why it's inconvenient for you to edit the source code?

Undefined ADT in r5rs

I'm writing an ADT in r5rs and I'm using DrRacket. I put #lang r5rs at the top of my file and chose Determine Language from Source from DrRacket, but it tells me my ADT is undefined. I'm using DrRacket version 6.0. It's the first time I've had this and can't understand what I'm doing wrong.
My ADT
#lang r5rs
(#%require "queue.rkt") ;A required file
(#%provide (all-defined))
(define (my-ADT)
(let ((val1 '())
(val2 '()))
(define (foo) ...)
(define (bar) ...)
(define (dispatch msg)
(case msg
((foo) foo)
((bar) bar)
(else "Unknown message")))
dispatch))
When I try to create an instance of my-ADT I get the following output: my-ADT: undefined; cannot reference an identifier before its definition
When I remove #lang r5rs from the top and choose R5RS as language in DrRacket, it seems to work. But then my queue.rkt file still has #lang r5rs at the top and Determine Language from Source. When I remote #lang r5rs and choose R5RS as language in that file also, I get the following in the my-ADT file:
default-load-handler: expected a `module' declaration
found: something else
in: #<path:/Users/path/path/path/queue.rkt>
The error
my-ADT: undefined; cannot reference an identifier before its definition
normally indicates that the function my-ADT was used before it was defined.
That is, one must place all definitions on top of the file and place the expressions below.
Your example above has no uses of my-ADT so if you get this error, the problem might be in "queue.rkt". Can you run "queue.rkt" without errors?

How to use `typed/racket` in `scribble/lp`

Is it possible to use other #langs in #lang scribble/lp for literate programming?
For example, I want to use #lang typed/racket in #lang scribble/lp. How to realize that?
TL;DR: There are two ways. First, you can simply put your code in a submodule, and require it immediately. Second, you can use my fork of scribble/lp2, which allows you to specify the underlying module language.
First method
Due to an issue, you'll have to wrap the whole thing in a (begin …), although there's a pull request which should fix this on the way.
#lang scribble/lp2
#chunk[<*>
(begin
(module main typed/racket
(define a : Number 1)
(provide a)
(module moo racket/base '…)
(module+ test
(require typed/rackunit)
(check-equal? a (+ 1/2 1/2))))
(require 'main)
(provide (all-from-out 'main))
(module test typed/racket
(require (submod ".." main test))))]
Bear in mind that these are submodule, so you can't put your test module inside main, as it won't be executed. Here, I have a (module+ test …) inside main, and it is required by a test module at the root level. If the (module test at the root is commented out, then the tests won't be executed.
The same concern applies also when requiring moo from another module, you'll have to use (require (submod "myfile.lp2.typed.rkt" main moo)), or make an "alias" like is done above for test and main.
Keep also in mind that the more nested a submodule is, the more times it gets visited and/or instantiated (not sure which). This can have a serious impact on the loading speed in typed/racket programs, as they are already themselves visited and/or instantiated multiple times. You can see this by adding (begin-for-syntax (displayln 'executed)) in your code, it gets printed many times.
Second method
My fork of scribble/lp2, hyper-literate (for hypertext literate programming) only alters scribble/lp2 and relies on the original version of scribble for the rest.
I don't guarantee backwards compatibility, as I'm currently fixing some bugs and adding extra features like being able to re-print a chunk to refresh the reader's memory, etc. The stackoverflow-q-18877881 branch I linked to should remain stable, though. Newer stuff will go in master.
Here's a small example file. There's a more complete example in test/test.hl.rkt:
#lang hyper-literate/typed typed/racket/base
#(require (for-label typed/racket/base
typed/rackunit))
#title{Title}
Hello world.
#chunk[<*>
(require typed/rackunit)
;; Would give an error as typed/racket/base is used on the #lang line:
;curry
(check-equal? ((make-predicate One) 1) #t)
(define (f [x : 'e123]) x)
(define ee (ann (f 'e123) 'e123))
(provide ee)]
It doesn't appear so, but you can use a typed/racket evaluator with scribble/eval.
#lang scribble/manual
#(require racket/sandbox
scribble/eval)
#(define my-evaluator
(parameterize ([sandbox-output 'string]
[sandbox-error-output 'string])
(make-evaluator 'typed/racket/base)))
#interaction[#:eval my-evaluator
(: my-sqr (Real -> Real))
(define (my-sqr x)
(* x x))
(my-sqr 42)]
Example taken from here.

How do I write a scheme macro that defines a variable and also gets the name of that variable as a string?

This is mostly a follow-up to this question. I decided to just keep YAGNI in mind and created a global variable (libpython). I set it to #f initially, then set! it when init is called. I added a function that should handle checking if that value has been initialized:
(define (get-cpyfunc name type)
(lambda args
(if libpython
(apply (get-ffi-obj name libpython type) args)
(error "Call init before using any Python C functions"))))
So now here's what I want to do. I want to define a macro that will take the following:
(define-cpyfunc Py_Initialize (_fun -> _void))
And convert it into this:
(define Py_Initialize (get-cpyfunc "Py_Initialize" (_fun -> _void)))
I've been reading through the macro documentation to try figuring this out, but I can't seem to figure out a way to make it work. Can anyone help me with this (or at least give me a general idea of what the macro would look like)? Or is there a way to do this without macros?
I've answered most of this question in the other one (I didn't see this one). It's fine to use a function that pulls out the bindings like this, but one possible problem here is that since you generate the binding only when the resulting function is called, this binding is re-created on each and every call. An easy way to solve this quickly is using promises, something like this:
(require scheme/promise)
(define (get-cpyfunc name type)
(define the-function
(delay (if libpython
(get-ffi-obj name libpython type)
(error "Call init before using any Python C functions"))))
(lambda args (apply (force the-function) args)))
But this is essentially almost the same as the code I posted in your previous question.
More random notes:
get-ffi-obj will accept a symbol as the name to bind to -- this is intentional, to make such macros (as in the last question) easy.
Using (symbol->string 'name) in a macro is fine. As I noted above in my comment reply to Nathan's comment, this means that it gets called at runtime, but mzscheme should be able to optimize that anyway, so there's no need to try and write some sophisticated macro that does the job at compile time.
Look inside the PLT directory -- you will find a collection called ffi. This is a collection of examples of bindings with various styles. Macros that create the bindings are very common in these examples.
Why don't you change the generated code to
(define Py_Initialize (get-cpyfunc 'Py_Initialize (_fun -> _void)))
and then have get-cpyfunc run (symbol->string name)?
Granted, there is probably a way to do this with syntax-case (I can never remember its syntax though), and definitely if you're using a Scheme with CL-esque define-macro.
It's not the complete answer, but I came up with a macro that meets both requirements (defines a variable and a string with the name of that variable):
> (define-syntax (my-syntax stx)
(syntax-case stx ()
[(_ id)
#'(define-values (id) (values (symbol->string (quote id))))]))
> (my-syntax y)
> y
"y"