Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
TermiC: Terminal C, Interactive C/C++ REPL shell created with bash (github.com/hanoglu)
70 points by pjmlp on Aug 22, 2023 | hide | past | favorite | 29 comments


An aside:

MIT had, decades ago, the Handy Board [1], which was like an Arduino for the 1990's. I built a few and really enjoyed the Interactive-C language [2] it employed (enjoyed).

That particular environment, a small hobby microcontroller, was an ideal one for interactive-ness. Want to determine some reasonable values for your ultrasonic distance sensor? Type a line of code in the monitor and you'll get back an analog value seemingly instantly.

The modern Arduino IDE could perhaps learn a thing from the Handy Board + Interactive-C IDE.

(I believe in fact the C was compiled to byte-code and then run on a thin interpreter on the Handy Board, but that's beside the point.)

(Also, tangentially, the 68HC11 was the first microcontroller I learned assembly for ... I have little experience with assembly but thoroughly enjoyed that command-set, that chip.)

[1] https://en.wikipedia.org/wiki/Handy_Board

[2] https://en.wikipedia.org/wiki/Interactive_C


omg, you answered a question that's been bothering me for decades. I was never told the name of this prototyping system in the 90's when I had the luck to get to play with on in highschool. thank you!!


This is a cute implementation. Though for anyone wondering, an actually interactive C++ REPL does exist: https://clang.llvm.org/docs/ClangRepl.html

See also: https://github.com/root-project/cling


"Fugayzi, fugazi. It's a whazy. It's a woozie. It's fairy dust. It doesn't exist. It's never landed. It is no matter. It's not on the elemental chart. It's not fucking real.”

recently i've been playing with clang-repl (i don't know anything about cling) and it exists like this^. yea it's there and there are some CI tests that are run and etc but if you think you're going to run real C++ programs through it, you're in for a disappointing day.

i'm not saying it'll never get there - i hope it does!


The ROOT interpreter cling (and cint before it) have always been known for being incredibly brittle. Segfaults are _extremely_ common. If you think you can continue your REPL session after most kinds of errors, you're mistaken.

It doesn't help of course that ROOT itself is a horrible mess of massive internal state.


yea i figured as much. clang-repl might be a ground-up reimplementation but i don't really have high hopes. of course it would be nice if C++ had a repl-like environment.


If you like interactive c/c++, how a look at https://github.com/jupyter-xeus/xeus-cling, that allow you to run the c/c++ repl in Jupyter, either in web interface, and terminal interfaces.


I'll second cling, when having to teach C/C++ to beginner programmers I usually start them out with cling to familiarize them with C statements/expression/printing before delving into functions.

(When teaching I view high token count for hello world as a pitfall, starting with a REPL I can dive directly into computation before they start getting stuck on syntax)


Just from the title I thought it was parsing C/C++ code with BASH, thank god it's not.


Someone has at least started down that road: https://m10k.eu/2023/07/29/pkgex-parser.html


I'm kind of confused what the use case of this would be.

So it's essentially saving you the trouble of having to put code into an "int main()" and putting declarations before it?

And then attempt to run the code after every line you type. Are there other examples of REPLs that work like this rather than all the state of execution being held in the REPL like I imagine Python does do it?

Can it Tab-complete identifiers I introduce in it? Actually, I suppose it's a single 115 LoC bash script, and I really don't mean to dunk on it, it's a neat little experiment. It just kinda made me wonder what REPLs are made for, for the first time. :D

Like I imagine a very basic "interactive" coding session (for any language) could also be achieved by having an editor open and saving after each line, or having that done automatically, and then in another terminal some script watches for those changes and compiles/interprets/runs it.

A REPL like python's is more like... having a debugger attached to your program, but it just sits at a breakpoint and let's you tell it what code to run next, and you can inspect variable contents and such.

Seems like languages that compile to machine code don't work all that well for REPLing, eh.


> like... having a debugger attached to your program

Maybe this answers your own question, it’s a great reason to use a REPL, and this is a good analogy.

One thing REPLs are good for is the ability to interactively work through syntax errors. Type a line, it has a problem, so just do it again. It doesn’t have to completely stop and start over like a compiler. Syntax errors are not a big deal for a small test file, but can be very annoying if you’re working in a big project with a big build system.

I’d say not having to save a file, not having to write the command line to compile it to another file, not having to write the command line to run it (while usually leads me to write a small makefile if I have to do it more than a few times), all in addition to not having to wrap the code in “int main()” all adds up to a nice convenient way to run small snippets of C/C++. It might be extra useful to optionally auto-include the most common headers, and perhaps offer some shortcuts for common things.

I test little snippets all the time like printing the bits in a floating point number, or checking the syntax for struct packing, or dumping a quick table of numbers run through a function, stuff like that. It’s a pretty common occurrence for me to want to run a small amount of C++ code without any workflow overhead.

I also use Python and JavaScript REPLs all the time too for quick tests, even though they also take files, and compile them.(!) All language compile to machine code, so I’m not sure I agree that has to do with how well a language works in a REPL. Python’s really not that great in a REPL, IMO: you can’t easily paste copied code into it because the indentation is usually wrong.


Julia compiles JIT to machine code, and I guess JS/TS and ruby too? All of those benefit from a repl for prototyping.

I think the biggest fail with most repls is the transition from the repl when you have that moment of "it worked" to having the working bits minus the stuff around it crammed into an idiomatic reusable thing. It is fairly easy in matlab, but I haven't found a workflow in Julia that does that well, tried dr. Doc strings, pluto, and vscode plugin. I'd welcome a rust repl too.



Developing the module functions with Revise.jl inside vscode and do REPL like things inside jupyterlab makes a pretty good workflow for me. And everytime I try some cpp REPL I end up using more Julia instead.


What matlab workflow do you use that makes transitioning from REPL to file easy?


Its nothing earth shaking. I just type edit foo.m, select the lines from the history that worked and copy them to the new file, perhaps doing a quick namechange or two. It isn't anything a plugin could provide, and doctor doc strings tries to, but it is pretty clumsy, the name change refactoring thing isn't there, and more importantly, the idiomatic way to create a reusable module in julia is a lot heavier. I also run into issues of collisions between the new module and the lines I copied. I'm sure it is all resolvable, it just feels clunky out of the box after using it lightly for a year or so. I can use numpy the same way as matlab mostly, its just really slow. I haven't found a prototyping language other than matlab that I don't find myself thinking "might as well write it in rust as long as this is taking", as I know I'll end up doing that anyway.


> the name change refactoring thing isn't there

what does Matlab provide wrt this? Does its editor have refactoring assistance now?

> the idiomatic way to create a reusable module in julia is a lot heavier

do you mean package creation?

> I also run into issues of collisions between the new module and the lines I copied.

what kind of collisions do you mean?

what would your ideal tool for this look like? you select parts of your REPL history, ask for some name changes in it, give it a package name, and have it generate a package? any other features or steps that come to mind as potentially helpful?


Matlab has some simple refactoring for names changes. Change a name and press shift+enter to change all other occurrences in the file.

Yes, package creation. The "right way" use create package.jl or whatever feels like a speedbump and requires setup.

When I import the newly created model, I have gotten name collisions with the playground remnants which you can't fully clear without restarting the repl.

That sounds like something I'd use, yeah. If you wanted to be fancy, you could make a function, putting uninitialized values into the argument list.


I guess the use case is to quickly try out some C/C++ code snippet. Typically I can think of checking binary arithmetic operations behavior.

Say you have some buffer that you need to align on 4K blocks, you could quickly try out your "& ~0x1000" in the REPL. It may not be a convincing example, but you get the gist, sometimes you just want to quickly see the result of some one liners.


I did what you described just yesterday. I couldn't remember offhand if the compiler I was using would automatically convert a uint8_t to an int (because I didn't want to have to add two levels of parentheses by explicitly casting the high byte and then shifting) and very quickly threw together a

    // test if we need a<<8|b
    //              or (a<<8)|b
    //              or ((int)a<<8)|b
    //              or (((int)a)<<8)|b
    #include <cstdio>
    #include <cstdint>
    int main()  { uint8_t a = 2; uint8_t b = 38; printf("%d\n", a<<8|b); }
More than half of the time is the uninteresting parts: writing the includes, creating a temp file, exiting to compile, forgetting a parenthesis, reediting and resaving, compiling again, running, deleting...

In a REPL---particularly one with stdio/stdlib included by default---this would take 30 seconds but instead takes 3 or 4 minutes. It's not much, but tight feedback loops really, really keep you in a great mental state.


> I'm kind of confused what the use case of this would be.

I imagine just about the same use case as running python3 interactively. Except, this is for C and C++.

Sort've like Compiler Explorer but on the command line.

Super cool.


This remind me about realcsh which is same concept. https://manpages.ubuntu.com/manpages/trusty/man1/realcsh.c.1... The package provides realksh which provide shell inside kernel. https://manpages.ubuntu.com/manpages/trusty/man8/realksh.c.8...


Nice script.

It's... uhhh... not shellcheck-clean.

https://shellcheck.net/


Missed opportunity to build a free alternative to Cling (“Clang-Repl” as it’s called now: https://clang.llvm.org/docs/ClangRepl.html) on GCCJIT


Wow, I was expecting a bash monstrosity, but at 120 lines it's actually very readable!

Cool project :)


Bash: interactive Bash REPL shell created with C

Full circle!


there is also "cplr - the C piler" https://github.com/promovicz/cplr


the c shell :)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: