contributing to tcl/parrot ^

A brief overview on how to help out, if you're interested. In general, it's ok to send patches for tcl to the RT system for anything that isn't "BIG STUFF" - those, please bounce off the MAINTAINERS first. We'd prefer diff -u patches, but are happy to take complete files as well.

Since partcl is bundled with the parrot source, svn access is handled via the same mechanism as for parrot itself.

BIG STUFF ^

Writing Builtins

partcl is a compiler. Given a section of tcl code, it translates that code into an AST (in the form of a Tcl* object from lib/*). Once a section of code has been translated, the object's compile method is invoked, which then generates PIR which can be compiled by parrot.

The commands themselves have (well, some of them do) inline-able (compiled) versions: These are located in src/builtin, and all new development should go there. There are many runtime-only versions that exist in runtime/builtin. In general, no new development should occur here. The inline-able versions are preferred, as they help avoid runtime dispatch.

When writing inlined builtins, these are further subdivided into two variants at the moment: those generated automatically by running tools/gen_inline.pl, and those that are handwritten.

Templates for inlined builtins look a lot like PIR (they are, for the most part) but they have a little bit of magic. The compiler takes care of argument handling and renames local variables and labels so they don't collide. Since we're using perl to generate the code, this is a one time cost at build time: at runtime, we are using PIR. (Which in turn generates PIR itself).

Hand-rolled inlined builtins take three arguments: a TclCompiler, an array PMC with the raw arguments, and an array PMC with the registers of the compiled arguments. Your return value is simply the compiler object. You should only use this method for generating builtins if a builtin cannot be defined using a template, and even then, extending the template parser is probably the right answer.

This is as opposed to the interpreted style in runtime/builtin, which takes a variable number of already compiled arguments at runtime. Our fallback method bundles these up, passing in a starting register of 0, and uses the resulting PIR to generate a .sub immediately and then invoke it. The runtime fallback is *always* going to be necessary for HLL interoperability.

Remember, every argument to your builtin is potentially variable and may change at runtime. You can check the type of the object at compile time. However, if it's constant, then you can optimize: for example, we could optimize [puts -nonewline "whee\n"] down to, basically, {say 'whee'}... however, we still have to be able to deal with [set a -nonewline; puts $a "whee\n"]. So, your first pass should probably do no optimizations. If you see a potential for optimization, however, at least add an XXX comment so we can get back to it later. At this point, we'd rather spend time working on new features than making existing features faster.

The results of calling the inlined code will be used by lib/tclcommand.pir. The inlined code is further wrapped in a protective conditional which will skip the inlined version if it can no longer be trusted (that is, if [proc] or [rename] has been invoked), and will fall back to the interpreted version as necessary. (And throw an exception if the command is not found at runtime.).

speed

We're currently slow, compared to tclsh. It's not worth worrying about this in terms of specific numbers until we can run tcltest natively. That said, any patches that improve speed without harming maintainability will of course be applied.

features

We're currently missing some things that require support from parrot. See hacks.pod for a list. In general, though, a lot of what we need to do is possible with parrot.

If you're looking for something to to do, see TODO one level up.

DOCUMENTATION ^

pod

Every PIR .sub that's defined should probably have some POD to go along with it to document the arguments and return values. Only exceptions to this should be subs which correspond directly to Tcl builtins -- those are already documented at http://www.tcl.tk/man/tcl8.5/TclCmd/contents.htm

PIR ^

Missing Commands

Every builtin command corresponds to an appropriately named file in src/builtin or runtime/builtin. Use a similar command as a template

If the return value would be TCL_OK, then simply .return the value from the sub. For any other return type, use one of the custom ops defined in "ops/tcl.ops" in src, e.g.: tcl_error.

Before adding new functionality, add a test (or a test in an existing) file in t/ - tests for puts, for example, go in t/cmd_puts.t. We are in the process of transitioning all our tests from the perl based Parrot::Test to a tcl-based version that generates TAP output. All new tests should be written using the tcl-based version. See t/cmd_expr.t for an example.

Our final goal will be to pass (most of) the tcl test suite: run make tcl-test to checkout the latest version of of the tcl test suite and run it. Warning: slow...

Long term goal is remove any tests in t/ that are testing things that are already tested in the official tcl suite. Partcl's checked in test suite should just be checking partcl-specific functionality.


parrot