If you're sure you want to get the raw program source and deal with it
manually, you can use the method `get-definitions-text
<https://docs.racket-lang.org/tools/drracket_unit.html#(meth._(((lib._drracket%2Ftool-lib..rkt)._drracket~3aunit~3aframe~3c~25~3e)._get-definitions-text))>`
on the DrRacket frame given as an argument to your button's callback
function. This will give you the editor object for the definitions window.
You can then use a method like `get-flattened-text
<https://docs.racket-lang.org/gui/editor___.html#(meth._(((lib._mred%2Fmain..rkt)._editor~3c~25~3e)._get-flattened-text))>`
to get the source as a sting or (probably better) the function `
open-input-test-editor
<https://docs.racket-lang.org/gui/Editor_Functions.html#(def._((lib._mred%2Fmain..rkt)._open-input-text-editor))>`
to get an input port directly. Before evaluating it, you need to convert it
to an s-expression with `read` or, better, a syntax object with
`read-syntax`. In either case, you will want to use `
with-module-reading-parameterization
<https://docs.racket-lang.org/syntax/module-helpers.html#(def._((lib._syntax%2Fmodread..rkt)._with-module-reading-parameterization))>`
to set the reading parameters properly.

However, if I understand your requirements correctly, I still think
expanding to a "main" submodule would be the best way to go. To be
concrete, I'll use the example I gave before of a partially-expanded
version of your program, but with `shape` renamed to `result` to match your
description:

(module example hypothetical-lanugage
  (#%plain-module-begin
    (provide result)
    (define result (hypothetical-code))
    (module* main racket/base
      (require (submod "..")
               hypothetical-lanugage/private/render)
      (render result))))

On Wed, Jun 26, 2019 at 12:05 PM Thomas Dickerson <
thomas_dicker...@alumni.brown.edu> wrote:

> 1. The language is a language for describing parametric 3D models, not for
> rendering, and the final result of being evaluated by Racket is a module
> containing a provided result value, which is a pointer to a C++ object
> which represents some a low level program evaluated by our C++ runtime to
> produce a triangle mesh.


Hopefully it's clear how this aspect of the expansion works: `
(hypothetical-code)` evaluates to your foreign C++ representation just as
it would in your current way of thinking about these programs.

2. Our C++ applications obtain the result value from a DSL program by
> calling scheme_dynamic_require in the inner loop of a Racket interpreter
> we've stuffed into a coroutine
> <https://github.com/Geopipe/CxxBidirectionalCoroutines/>.


Again, this part works just fine. In particular, because of the way Racket's
submodules
<https://docs.racket-lang.org/reference/eval-model.html#%28part._submodules%29>
work, the code in the "main" submodule *does not* run when you instantiate
the parent module, whether via `scheme_dynamic_require`, `dynamic-require`,
`require`, or some other way: the compiled form of the submodule need not
even be loaded into memory. So you can use rendering code in the main
submodule without creating a dependency for your main application.

3. When the toolbar button is pushed in DrRacket we want to evaluate the
> program in a fresh namespace, (dynamic-require ''module-name 'result),
> and then pass that result value into a C++ FFI function that will handle
> the C++ side of evaluation and doing the actual OpenGL calls to visualize
> it in the editor. This should have similar behavior to the run button from
> an evaluation standpoint, but after evaluating the program, enter a render
> loop until, e.g. the button is pushed again to stop rendering. Here, the
> DrRacket plugin is responsible for creating the OpenGL context, which could
> be in a separate window, but as Kshitij said it would be ideal if we could
> figure out how to add a pane below the REPL.
>

This is where I think using a submodule will be helpful. When you press the
"Run" button in DrRacket, the "main" submodule is run for effect before
starting the REPL. (Command-line `racket` will do similarly depending on
the flags.) In the example expansion, `(render result)` would pass the
value described by your DSL program to your rendering function and whatever
FFI calls are needed. It could certainly open a new GUI window, and it
could also return a value that renders as an embedded widget (snip) in the
interactions pane. (See the plot library for an example.) I haven't looked
at the DrRacket extension APIs enough to be sure whether you could open a
new pane in the DrRacket window, but it certainly seems possible.

Using a "main" submodule should let you take advantage of DrRacket's
programming-languages-as-operating-systems capabilities for managing the
programs it runs with minimal additional work. DrRacket would take care of
destroying your rendering context when you click "Run" again after changing
your program, it could enforce memory limits, and its "Stop"/"Kill" button
could terminate misbehaved rendering code. You could re-create all of these
capabilities yourself, but that's a fair amount of work, and I'm not seeing
a compelling reason for this to be an extralinguistic tool.

-Philip

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CAH3z3gZ2DccaWO-qZ3rtzPXbRCpd%3DKp2dswug6orB-DG0VRXjQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to