leftmike / foment

Foment is an implementation of R7RS Scheme.
MIT License
67 stars 4 forks source link

Is it possible to embed foment into a c++ app? #32

Closed gamagan closed 5 years ago

gamagan commented 5 years ago

Can Foment be embedded into a C++ app such that it provides Scheme scripting capabilities to the app? Or, is Foment fundamentally built around the assumption that it will run as a standalong exe?

If the latter, then I imagine that there are assumptions in the codebase (Like, if there are globals used), which could make it incompatible for embedding.

This looks like a really sweet Scheme implementation. I hope that it's possible to use it embed.

Also, another question for which I didn't find an answer. Does the VM operate on bytecode or on the parse tree?

leftmike commented 5 years ago

Yes, I certainly intended that it be possible to embed Foment into a C++ app. There are globals used, but that shouldn't prevent embedding. I am happy to work with you to get Foment embedded into your app.

Can you share what sort of application you want to embed Foment in and provide details about how you want to use it for scripting?

The VM operates on bytecode.

gamagan commented 5 years ago

Hi, leftmike, thanks for getting back to me.

Currently, I'm evaluating different scripting language to embed into my game engine. Since this is a personal project, I'm trying to avoid going with a boring but safe language, like JavaScript or Lua. I'm trying to not be completely bored while scripting the game. My current choice of scripting language is Scheme, but I have some reservations, based on the outlook of the Scheme landscape. Apparently, most schemes are not created to be embedded, which was a surprised to me. There are my current requirements:

I know the bullet points related to the GC are probably difficult ones to meet. Those are on the fairly advanced side. But, for real-time games, they are very nice to have.


Additionally, and this is not a requirement but a nice to have, I'm considering creating a slightly modified version of the Scheme syntax, to put in some adjustments that I prefer.

It would be extra nice to have the compiler for this updated syntax be able to provide IR to the Scheme implementation so that it can skip the parsing phase -- to avoid doing parsing work twice. Though, this one is probably on the advanced/impossible side since, I assume, Scheme implementations generally execute side effects during parsing.

For the syntax changes, I'm think of:

I'd still like to keep the Scheme semantic model, but would make the syntax more of my taste. Again, this syntax business is not a requirement; just some nice gravy.

leftmike commented 5 years ago

If you go with Javascript, take a look at V8. You also might want to look at Chibi scheme.

There are my current requirements:

  • Designed to be embedded, so no fighting against the library to get it to embed into C++.

I had embedding in mind when I implemented Foment, though it has not yet been embedded, so I am sure there would be some rough edges.

  • Windows as a first-class OS target, not an afterthought (the game engine runs on Windows) -- so no cygwin/mingw.

The vast majority of the original implementation was done on Windows and all of the supported operating systems will always be first class targets.

  • Runs either bytecode or JIT, so not one that compiles to C code or into a native library.

Yes, bytecode.

  • It's not super slow.

Foment could be much faster: the compiler is pretty stupid.

  • The game engine owns the main loop, not the Scheme.

Take a look at main.cpp for a couple of different ways to call scheme code.

  • Supports R7RS small.

Foment supports a subset of R7RS large as well.

  • No use of global variables, so that I can run multiple VMs at the same time, on multiple threads. Something on the order of 4-8 interpreters.

Foment has global variables and this would be a lot of work to change.

Why not a single VM and call into it from multiple threads which Foment does support?

  • Can pause and unpause the GC.

This would be easy to add to Foment.

  • Ideally, can manually trigger a GC collection, while giving it a time window in which it should perform it's work. That is, given 5ms, it should do what it can within that time, but not go over (I know it will go over time by a little, but you get the ideal).

Manually triggering a GC is supported. Having a time windows is not supported. Interesting problem though. I did put some work into a generational GC which mostly works. The global mark and sweep collector is more reliable.

  • Memory malloc/free functions would be provide by the engine to the VM so that the VM fetches memory from engine-defined memory pools.

This would be easy to add to Foment.

  • No GPL/LGPL licenses.

Agreed. (Foment has no GPL/LGPL code or licenses).

I know the bullet points related to the GC are probably difficult ones to meet. Those are on the fairly advanced side. But, for real-time games, they are very nice to have.

Interesting problems though.

Additionally, and this is not a requirement but a nice to have, I'm considering creating a slightly modified version of the Scheme syntax, to put in some adjustments that I prefer.

It would be extra nice to have the compiler for this updated syntax be able to provide IR to the Scheme implementation so that it can skip the parsing phase -- to avoid doing parsing work twice. Though, this one is probably on the advanced/impossible side since, I assume, Scheme implementations generally execute side effects during parsing.

For the syntax changes, I'm think of:

  • Make top-level declaration parenthesis optional; the parser would fill those in automagically. -- So (define foo 5) -> define foo 5
  • Remove parenthesis from lambda declarations: (lambda (a b) (body)) -> \a b(body)
  • Make lists be comprised only of [...] --> (1 2 3) would be a tuple or function call.
  • tables written as {key:value key2:value2}
  • Access table and list elements via dot --> {value:42}.value, [5 6 7].0
  • A few other changes like this.

I'd still like to keep the Scheme semantic model, but would make the syntax more of my taste. Again, this syntax business is not a requirement; just some nice gravy.

Again, reasonably straightforward to do. Take a look at SRFI 119: wisp: simpler indentation-sensitive scheme and all of the SRFIs.