I woke up last night with a conviction that C++ is not a worse “scripting” language than Perl or Ruby. After a few minutes awake, I had to turn on the computer and prove this nightly conjecture. I created a draft scripting environment for C++ in a few hours.
I call my nocturnal embryo cpsh for “C++ Shell.”
Of course, after writing it, I discovered one quite more ambitious scripting project for C++: CINT. This alternative is - I believe - less compliant with C++ than my scripting environment and far more verbose than mine and, yes, they use C. And, I bet they did not implement it over one drowsy night
My solution was very simplistic, just build a layer on top of GCC. I will port this to work properly with VC 7.1 when I get a few more hours over. What cpsh does, in essence, is to feed GCC with the code as the user types it, or as provided by a script file.
The scripting language is C++, with most goodies included. There is a flag one can switch, which decides whether to use Boost or not.
cpsh can read the script from standard input or from a file. It can also work in interactive mode, yielding the result of each statement as typed.
I first (like between 2 AM and 3 AM…) played around with trying to execute the construct as is, and if that failed, it will add proper constructions to output the given expression. I finally (around 4:15 AM) decided to have four types of statements for my script language:
- top-level definitions - these are put at the global level
- regular statements - these are put inside the main function and will be executed
- queries - these expressions, which will be executed and have its value displayed
- admin commands - changes the environment, such as enabling and disabling use of Boost
Ok, enough talk. Let us show an interactive session with this scripting environment (yes, it is a C++ shell as well
)
c:\proj\cpsh> cpsh -i
> ? “hello ” + “world”
# Problem. Compilation error. query:1: error: invalid operands of types ‘const char[7]’ …
> ? string(”hello “) + “world
< hello world
You see that I run it on Windows, which is fine, as long as you have GCC available and the shell can interpret the standard output redirector directives of Unix. Try MinGW, for instance.
Here I tried to add two char pointers, which is an invalid operation. Coercing one of the char pointers to a string did the trick, though. I only used query statements, starting with ‘?’.
Let us look at a more interesting interactive session, where we try to find out how vectors work:
c:\proj\cpsh> cpsh -i
> vector<string> names;
> ? names.size()
< 0
> const char* namePtrs[] = { “Hilda”, “David”, “Nicole” };
> names.assign(namePtrs, namePtrs+3);
> ? names.size()
< 3
> copy(names.begin(), names.end(), \
>> ostream_iterator
{Hilda David Nicole }
> ? sizeof(names)
< 12
>
>> T twice(T t) { return t + t; }
> ? twice(2)
< 6
> ? twice(string(”david is best “))
< david is best david is best
Yes, I am. And humbly so. Lines beginning with ‘.’ mark top-level declarations and definitions, and trailing a line with ‘\’ allows you to continue expressing yourself on more lines before the interactive environment compiles and runs the code. NOTE 1: Any output from the statements is embedded in {…}. NOTE: if you happen to type invalid code, do not fear; the environment automatically rolls back to the last happy compilation.
This is a great tool for exploring not only C++ but also Boost (whereof some libraries will be part of TR1), and the runtime constraints. We continue the session:
> ? sizeof (int)
< 4
> ? sizeof (long long)
< 8
> :b+
# Enabled Boost
> function<int (int)> myFun;
> myFun = twice
> ? myFun(10)
< 20
> myFun = bind(twice
> myFun(10)
> 4
NOTE: the reponse time is currently a bit slower when Boost is enabled. “A bit” as in “300%”… Here I tested both the function and bind from Boost.
I believe this tool will also come in handy when teaching C++, where the student can use trial-and-error with immediate response.
Once having this scripting engine, working closely with a compiler, one can fantasize about producing a proper web framework, mush like Joe Morrison’s Eleven. Think “C++ on Rails”
I will write more about both the use and implementation of this cpsh later, with a focus on how typical scripting tasks (like traversing files looking for patterns) are achieved in cpsh. Additionally, I will provide a compiled version for Windows and Ubuntu.
Just need a few free hours