That's exactly how CINT was used in ROOT, but now they're moving to Cling instead. Clang compilation is sufficiently fast for an interactive development.
After years of dealing with Graduate student missteps and ROOT->Java interoperability, to me, ROOT will always mean: blown stacks (i.e. double hist_data[1000000];), poor documentation on TTree/TBranch, NPEs, exceptions, the horrible bag of "features" TObject is, terrible debug statements, no logging, GUI hell, pseudo-.C-macro-compilation-that-only-works-with-trivial-cases, code translation, dlopen madness, code interoprability, Mac OSX support, 2+ hour compilations, TList hell because no STL (NO STL!?!?!), etc...
Years of physicists time has been wasted on CINT, and many more years on ROOT itself.
I'm sure Cling is much better, and it looks cool on it's own, but I know ROOT isn't. Luckily I only have to dig in the source code for ROOT once a year or so (the last time was figuring out they finally got around to adding LZMA compression to ROOT files when things started breaking at work).
I used to think PyRoot was the way forward. Eventually, ROOT will be burned at the stake and everyone will over with Julia.
One of my favorite early Rust features, in theory, was the interactive shell called "rusti". In practice it was awful to use because it was slow, crashed all the time, and required whole blocks of code be entered at once (declaring, defining, and using a variable for example). Some of that was attributable to beta status of the language but it seems like they ditched it in the end. Is there actual value to this sort of thing for languages that are classically compiled instead of interpreted? At least for Go, Rust, and C speed of compilation is less of an issue overall but compiling C++, even with clang, is so much of a bear that I can't see this catching on.
Slow compilation time is actually a great reason for having a REPL. e.g. Clojure and Julia are both REPL-based languages, though both secretly need to be compiled (and do so relatively slowly). In practice you don't notice the compile step at all, since after compiling and running once you can just compile 1-2 lines at a time in the REPL and it patches the running program for you – it's all instant.
A more interesting issue for REPLs is how expression- or statement-oriented the language is (c.f. Martin Odersky's concerns about the upcoming Java REPL). In Java/CXX it's much more likely for a function to want to change an external object, in which case you'll need to set up the environment, run the code, check the environment for the change, for every line you write. That's much more likely to be the nail in the coffin for this.
This might be interesting. I'm not actually interested in C++ (any more) but I'm still looking for the easiest possible way for me to get into LLVM. I think “learning LLVM” seems like the obvious next iteration of what used to be “learning assembler”, except this time around, it's actually portable. I love experimenting with languages and having an LLVM backend ready at my fingertips must feel like Programmer's Heaven...
I highly recommend the LLVM Kaleidoscope tutorial. [1] It takes you through all the steps required to implement a REPL for a simple single-type language, and is surprisingly concise given the end result.
Regarding the JIT aspect, if you are like me, you will be in awe when you encounter the single operation
f_ptr = engine->getPointerToFunction(f_def)
It turns a function definition (in LLVM IR) into an actual function pointer that you can invoke just like any other C/C++ function.
How does something like this work in general? My naive idea about how to make such a thing essentially seems like a virtual machine, which is quite a bit of effort.
In principle, you can use any compiler of your choice to fake this: Just create a dynamic library for each line that has been entered into the REPL that you immediately load and call into.
Now, 'all' you need to do is cut out the middleman and directly output properly relocated code to memory. There are compilers that can do so. Clang/LLVM is one one of them. TinyCC is another.
If so, isn't that rather similar to how Visual C++ allows you to modify code in flight while debugging by rolling back to the beginning of the function call?
The word "dynamic" in the grandparent post refers to dynamically relocatable object files, i.e. all the memory references in the binary are written as relative offsets so that the binary doesn't assume anything about what address it will have within the process when it gets loaded. Concretely, this means the difference between "JMP 0xDEADBEEF" versus "JMP (special_register)+0xBEEF" so that the .so or .dll file doesn't assume it'll get loaded at 0xDEAD0000.
Cling relies on LLVM JIT, the same way as many other LLVM-based languages with REPLs. For each interactively added piece of code it creates an LLVM module, compiles it and jumps to its entry point.
Hey Guys! If you want, you can see Cling in action in a Terminal.com VM. I've just created a snapshot with Cling up and running and some documentation also. https://www.terminal.com/tiny/o1MgFbPB2L
Another option is Ch from Soft Integration [1], which has been making commercial grade C/C++ interpreters for a long time. The standard package is free and it comes with an IDE.
Well, it hooks into your code in the sense that you can expose classes and libraries to it.
One use is for C++ "scripts". Clang replaces the older "C interpreter CINT" in ROOT (which is mainly a data analysis framework for particle physics). CINT was horrible because it was "not quite C++", and encouraged bad behavior. You could swap . and -> for example; objects that were saved to a file you loaded appear automatically in scope (without prior assignment), templates were a bit iffy and so on. You could run many .cpp files as CINT scripts, but not the other way around. So current best practice is to avoid the"interpreter" and write proper programs that link to libROOT. Cling seems to be much more sane.
I don't know if you need something like that, but one thing Cling/CINT gives you is reflection/introspection, which is pretty neat. I think it's also somehow used to get generate bindings for other languages. Oh, and having a Repl is pretty nice. I use it e.g. for quick plots:
$ root filename.root
[0] tree->Draw("mass")
(where "tree" is a data structure automatically loaded from filename.root containing data points, and the command makes a histogram of "mass")
I can definitely see myself just using a simple REPL. I don't use C/C++ that often, so being able to start an interpreter and executing just of few line of code would be great. A use case would be checking the exception semantics of C++, or which element boost::bissect returns when you have several equal values.
Depends, if WTL is plain C++ and compiles with Clang, then it should. If it uses MSVC extensions (like `guidof`) then it won't work. (I've never used WTL besides a little Hello World test.)