About Picol Richard Suchenwirth, 2007-04-06 Picol was originally created by Salvatore Sanfilippo in March 2007. It is a small scripting language modeled closely on Tcl (Tool Command Language), with very little effort - Salvatore's first published version had just 500 lines of C code. License is BSD. Picol is of course a very small language, allowing so far only integer arithmetics, and lacks many features of "big Tcl". In spirit it is close to pre-8.0 Tcl, where every value was indeed a string, and [expr $a+$b] would require two atoi() scans and another sprintf() formatting. Also, arrays are not supported in Picol. Having used Tcl/Tk for about ten years, and C even longer, I still never looked much at the C side of the Tcl implementation. Many things were introduced in that time: bytecode compilation, Unicode support... leading to a code base of considerable complexity. I settled for letting the maintainers doing their job, and me being just a "consumer". Looking at the source of Picol (it is in fact a single file, picol.c, with no dependencies other than the usual stdio/stdlib), I felt that this code was transparent enough for the man in the street. I could understand the architecture (except maybe for the parser :^) and easily see what was going on, how commands were registered and implemented, and so on. The executable can, like tclsh, run either interactively, where you type commands to a prompt and watch the response, or in "batch mode", when a script is specified on the command line. Salvatore's original version had just eight commands: proc, puts, if, while, break, continue, and return, in addition to about ten arithmetic and comparison operators as known from [expr], or especially LISP. Salvatore decided not to implement [expr], with its own little language with infix operators, whitespace being mostly redundant, and f($x,$y) notation for functions. Picol still does only integer math, and comparison operators are also limited to integers. In doing [if] and [while] he deviated from the Tcl practice that the condition arguments are in [expr] syntax, but rather scripts like everything else. This however meant that Picol is an incompatible dialect of Tcl - it is similar in many respects, but the different interfaces for the frequently used [if] and [while] commands excluded the possibility that non-trivial Picol scripts could run in tclsh or vice-versa. Still, Picol fascinated me - not as a tool for serious work, just as an educational toy. "Camelot!... It's a model." I began to miss features from tclsh, like leaving the interpreter with [exit], so the first thing I did was to implement an exit command, which was pretty easy. What I also missed was the one-argument [gets] as simplest way to inspect variables interactively. And access to global variables from inside procs. And a [source] command. And... you can guess what happened. I became addicted with Picol. Never before in a long time of coding in C has the bang/buck ratio been so high. Especially, standard C libraries offer rich functionality that can rather easily be leveraged. For instance, most of [clock format] is available from strftime(), it just remains to call it. My partial implementation of [clock] provides clock clicks|seconds|format, all from 18 lines of C code. But two things bothered me: the incompatibilities with real Tcl, and the lack of the so popular list operations. Fortunately, on Good Friday 2007, I managed to think up simple solutions for both of them. Where in Tcl you would have a condition as expression if {$x < 0} ... in Picol you'd use a short script with a prefix operator: if {< $x 0} ... which looks similar enough, but can't be parsed as valid expression by Tcl. On the other hand, the possible Tcl notation (if you have a [<] command), if {[< $x 0]} ... would be double-evaluated by Picol, leading to an error "unknown command 0" (or "1"). The solution I came up with overnight was to introduce the elementary identity function, like proc I x {set x} and a variation of picolEval which just prepends "I " to the input script, and evaluates that. This way, both function results and numeric constants could easily be used in Tcl syntax, and eight more lines of code solved that incompatibility problem. From that point on, I wanted to test my Picol test suite with tclsh as well, just to make sure that the two languages don't diverge. I first did this by hand, but very soon got the idea that a minimal [exec] is feasible for Picol too, so here's what I coded: int picolCmdExec(struct picolInterp *i, int argc, char **argv, void *pd) { char buf[1024]; /* This is far from the real thing, but may be useful */ int rc = system(picolConcat(buf,argc,argv)); return picolSetFmtResult(i,"%d",rc); } The caller doesn't get the stdout of the called process back, and there isn't much configurability, but this minimal solution allowed me to include the line exec tclsh [info script] in my test suite, and thus conveniently testing two things at once - Picol, and the compliance of the test script with Tcl. Some tests have to be skipped for Tcl, of course - though the arithmetic/comparison operators are provided, things like [info globals] or [expr] error messages are not easily unified. I base the skipping of tests and other conditional code on [info exists tcl_version]. Another modification I find useful is to allow a script on the command line. If the first argument is "-E", the second is evaluated as script, its result displayed on stdout, and then exit. This feature is known from Perl and comes quite handy sometimes: /_Ricci> picol -e "lsort [info commands]" ! != % * + - / < <= == > >= _l abs append array break catch clock close concat continue eof eq error eval exec exit file flush for foreach format gets if incr info interp join lappend lindex linsert list llength lrange lreplace lsearch lset lsort ne open pid proc puts read rename return scan seek set setenv source split string subst switch tell time unset uplevel while /_Ricci> which by the way exhibits how many familiar commands have been added to Salvatore's original version... As there was no version numbering, I dubbed it 0.1.0, and have been adding patchlevels, one after the other, up until the current 0.1.16. Will there ever be a 1.0 version? I have no idea. Creeping featuritis is always a danger, and it might be a pity if the clear Picol design gets obscured by yet another bell here and a whistle there. Vital statistics (subject to change without notice): Number of source files 1 (picol.c) Lines of code 1079 Implemented commands 55 Number of test cases 66 (in test.pcl) Size of stripped executable 23552 bytes A ZIP file containing picol.c, test.pcl, and this document can be downloaded from http://mini.net/files/picol0-1-17.zip . License conditions are again BSD, i.e. free for all private and commercial use, provided the original authorship is acknowledged. And no warranty for any usability for any purpose, but you know that :) For me, the main purpose has been to experiment with C without the hassle of complex dependencies. Hacking on Picol, I felt how a student at UC Berkeley must have felt in 1988, when Tcl was just a baby...