Tcl in Javascript

Hmm. Interesting - so should I assume this is only core tcl, no tk etc?

Also Google Code, why? How about GitHub? http://www.quora.com/GitHub/Why-do-people-not-use-Google-Code-instead-of-GitHub

RS 2013-11-11: The tcljs project now has a home at http://code.google.com/p/tcl-js/ . Version control via mercurial. Also via Fossil at https://chiselapp.com/user/suchenwi/repository/tcl-js/dir?ci=tip

Note: I used to develop this with node.js v0.6.19 (which was standard via apt-get). Now that backslash escapes are finally working, the test suite (which is in UTF-8) needs to be parsed as such, so I upgraded to node.js v0.10.22.

Feel free to get it, test it, criticize it...


This work has been furthered by apw in incr Tcl in Javascript - MartinCleaver


Sarnold: I created a Tcl implementation in JavaScript. The idea came from the need I felt to process documentation in wiki form in a browser - i.e., store manuals as wiki markup directly on the server, and let some JavaScript code process it.

This idea is not new; many AJAX applications already do it. But remember, Tcl was created as a configuration language, and I need this type of language. But I wonder if I will ever have the time to finish it.

JsTcl - this implementation is far from being complete. I began it by looking at Picol's parser code, and converting it into JavaScript.

Downloads

You will need:

  • Jstcl [L1 ] (LV Alas, that URL appears no longer to work), the Tcl implementation (currently 0.4).
  • wiki-resident copy: tcl.js, tcl.js 0.4
  • a demo with the official test suite is included in the zip archive

Supported platforms (browsers?)

This implementation was tested with Firefox 2.0.0.10 and IE 7.0 on Microsoft Windows XP.

 puts {Really, Tcl runs everywhere!}

Differences with standard Tcl

Like in Picol, we have no expr. Instead, we have:

 + - * / % = !=

which operate on integers/reals, and

 not and or

which operate on booleans (there *is* a boolean type in this implementation).


RS: tcl.js is indeed a lovely baby, though so far poorly equipped (e.g., no loop commands like for, foreach, while...). I had to add

    this.registerEasyCommand("<", function (interp, args) {
        this.requireExactArgc(args, 3);
        var a = args[1].getNumber();
        var b = args[2].getNumber();
        return (a < b);
    });

or, simpler,

    this.registerEasyCommand("<", function (interp, args) {
        this.requireExactArgc(args, 3);
        return (args[1].getNumber() < args[2].getNumber());
    });

to get one of my favorite test cases through (ignore the backslash before * - Wiki is over-aggressive with that):

 proc fac x {
    if [< $x 2] {return 1}
    \* $x [fac [- $x 1]]
 }
 puts "fac 5 = [fac 5]"

But it wasn't hard - just a matter of copy'n'paste :^) On IE 5.50, the demo page didn't work, but it did in Opera 7.54 (except for source.. which lacked a good treatment for XMLHTTP). In any case, putting the test code right into jstcl.html works fine. Or using IE 6 on Win XP :^)

My latest version is tcl.js 0.4

Sarnold 2007-11-16 : I put my file in sync and added the "native" command. Here is how native should be used:

 native add {function(interp, args) {
        this.requireExactArgc(args, 3);
        return args[1].getNumber()+args[2].getNumber();
 }}

It allows users to extend tcl.js with plain Tcl files, like Critcl allows us to extend Tcl with commands written in C.

LV 2007 Nov 16 I guess I don't get the example. It doesn't look like a plain Tcl file, which you seemed to indicate was the purpose for native. Instead, it looks like plain JavaScript code. Is that what you meant to say? I thought that you would extend the tcl of tcl.js just by doing a source (as is demonstrated on the example page....)

Also, did the other functions mentioned on this page make it into this version of tcl.js? The clock command, for instance.

RS Yes, clock is there :^) Sarnold's example above is one Tcl command, where the third word happens to be Javascript code, and which creates a Tcl command "add" which calls the given JS function. Somehow like Critcl's cproc with C body. For a lighterweight variation, see also jseval below. - However, native seems not to work in IE6, the following code shows that input is right, but func is undefined:

    var func = eval(args[2].toString());
    alert("in: "+args[2].toString()+", func: "+ func);

RS: Playing more with Javascript, it's fun to see how similar it is to Tcl in spirit, even though different. For instance, to roughly approximate the clock command, it just took these few lines of wrapping code:

  this.registerSubCommand("clock", "format", function (interp, args) {
    var now = new Date();
    now.setTime(args[1]);
    return now.toString();
  });
  this.registerSubCommand("clock", "scan", function (interp, args) {
    return Date.parse(args[1]);
   });
  this.registerSubCommand("clock", "seconds", function (interp, args) {
    return (new Date()).valueOf();
  });

or this, one up the meta ladder: JS evaluates Tcl that evaluates JS:

  this.registerCommand("jseval", function (interp, args) {
    return eval(args[1].toString());
  });

A language that has eval can't be all bad :^) Testing:

 puts [jseval "6 * 7 + Math.min(2,1,0);" ]
 42

This allows us to add Tcl commands as procs which probably aren't even so inefficient, as ultimately the JS interpreter eats its own food:

 proc sqrt x {jseval "Math.sqrt($x);"}

LV 2007 Nov 14

Note that I ran the jstcl.html test suite using Windows IE 6 and Windows Firefox 2.0 and the tcl.js 0.2 worked fine with the test suite there.


CMcC 16Nov07 added a "dom" command which implements a half-assed interface to http://jquery.com/ giving a DOM interface. By including the jquery script, it allows stuff like this:

    dom "<div id='fred'><p>Hello</p></div>" appendTo body; dom #fred css border "1px solid gray"

 which adds a paragraph to the end of the document and puts a gray border around it.

    this.registerCommand("dom", function (interp, args) {
    var selector = args[1].toString();
    var fn = args[2].toString();
    args = args.slice(3);
    for (var i = 0; i < args.length; i++)
      args[i] = args[i].toString();
    if (args.length == 1)
      var code = args[0];
    else
      var code = args.join("\",\"");

    var script="$(\"" + selector + "\")." + fn + "(\"" + code + "\")";
    //alert(script);
    eval(script).toString();
    return "dom  " + selector;
    });

So cool. Note: if you need to quote something in one of the args, best to use js's apostrophe quoting.

The choice of jquery as a target library to wrap was guided by the fact that jquery uses string 'selectors' to choose javascript dom objects, which makes it easy to use within tcl in that you don't need to wrap raw javascript objects.

This package allows one access to the html dom from tcl.js, and permits dhtml and ajax from tcl.js.


RS: Cool indeed! It helped me to get a better implementation of puts (that is, no more alert() popups, instead output is added to the browser window), provided that jQuery is loaded:

  if(typeof(jQuery) != 'undefined') {
    this.eval("proc puts s {dom \"<div style='font-family:Courier'>$s</div>\" appendTo body}");
  }

The same check could be put around the "dom" definition above.

JBR: Better you can use any dom id to "puts" to different "streams".


See also: Picol - A little tcl.js console


See also an article by Patorjik Don’t want to use JavaScript? What about Tcl? Or LOLCODE? [L2 ] with another Tcl port of Picol.


2008-03-28 The Ruby folks now have a similar Ruby-in-Javascript, but with a twist: Ruby code is compiled in a C-coded Ruby implementation via a CGI script, then the opcodes are executed in a Javascript based Ruby VM:

See HotRuby: http://hotruby.accelart.jp/ and http://ajaxian.com/archives/hotruby-run-ruby-on-a-javascript-interpreter


jima (2009-10-05)

Interesting: perl 6 compiler implementation for javascript [L3 ].

And more languages that choose javascript as compiler target [L4 ].

I would say this is a serious trend.


GS (20121218) Another example with Brython : [L5 ] a Python implementation with a clock demo in html 5.


Tcl.js (Cyan Ogilvie)


tcl-js is an interpreter for Tcl written in typescript, it tries to replicate the tclsh interpreter as closely as possible. This interpreter is not built for speed or efficiency, but for security, ease of use and modularity.