- Notifications
You must be signed in to change notification settings - Fork5
A simple/minimal TCL interpreter, written in golang
License
skx/critical
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
After re-readingTCL the Misunderstood, I decided to create a simple TCL evaluator of my own. This project is the result, and it has feature-parity with the two existing "small TCL" projects, written in C, which I examined:
There is a simple introduction to this project, and TCL syntax, on my blog here:
The name of this project was generated by looking for words containing the letters "T", "C", and "L", in order. I almost chose
arTiCLe
,TreaCLe
,myThiCaL
, ormysTiCaL
.Perhaps somebody else can write their own version of this project with one of those names!
This repository contains a TCL-like interpreter, along with a sample driver.
You can build both in the way you'd expect for golang applications:
$ go build.
Once built you can execute the application, supplying the path to a TCLscript which you wish to execute. For example:
$ ./critical examples/prime.tcl 0 1 2 is prime 3 is prime ..
The interpreter contains an embedded "standard-library", which you can view atstdlib/stdlib.tcl, which is loaded along with any file that you specify.
To disable the use of the standard library run:
$ ./critical -no-stdlib path/to/file.tcl
Generally the point of a scripting language is you can embed it insidea (host) application of your own - exporting project-specific variablesand functions.
You'll find an example of doing that beneath theembedded/ directory:
The following is a simple example program which shows what the code here looks like:
//// Fibonacci sequence, written in the naive/recursive fashion.//procfib {x} {if { <=$x 1 } {return 1 }else {return [expr [fib [expr$x - 1]] + [fib [expr$x - 2]]] }}//// Lets run this in a loop//set i 0set max 20while {<=$i$max } {puts"Fib$i is[fib$i]"incr i}
Another example is the test-code which @antirez posted with hispicol writeup which looks like this:
procsquare {x} { *$x$x}set a 1while {<=$a 10} {if {==$a 5} {puts {Missing five!}set a [+$a 1]continue }puts"I can compute that$a*$a =[square$a]"set a [+$a 1]}
This example is contained within this repository aspicol.tcl, so you can run it directly:
$ ./critical ./picol.tcl I can compute that 1*1 = 1 I can compute that 2*2 = 4 ..
Additional TCL-code can be found beneathexamples/.
The following commands are available, and work as you'd expect:
append
,break
,continue
,decr
,env
,eval
,exit
,expr
,for
,if
,incr
,proc
,puts
,regexp
,return
,set
,while
.
The complete list of standardTCL commands will almost certainly never be implemented, but pull-request to add omissions you need will be applied with thanks.
Read the fileinput.tcl to get a feel for the language, but in-brief you've got the following facilities available:
- Floating-point mathematical operations for
expr
+
-
/
*
%
.
- Comparison operations for
expr
<
>
<=
>=
,==
,!=
,eq
,ne
- Output to STDOUT via
puts
. - Inline command expansion, for example
puts [* 3 4]
- Inline variable expansion, for example
puts "$$name is $name"
. - The ability to define procedures, via
proc
.- See the later examples, or examine code such asexamples/prime.tcl.
The biggest missing feature is the complete absence of support for lists of any kind. This is common in the more minimal-TCL interpreters I examined.
The other obvious missing feature is support for theupvalue
command, which means we're always a little at risk of scope-related issues.
Addingupvalue
would be possible, but adding list-processing would be more work than I'd prefer to carry out at this time - see #19 for details of what would be required to implement this support.
Our code has 100% test-coverage, which you can exercise via the standard golang facilities:
$ gotest ./...
There are also fuzz-based testers supplied for thelexer andparser packages, to run these run one of the following two sets of commands:
cd parsergotest -fuzztime=300s -parallel=1 -fuzz=FuzzParser -v
cd lexergotest -fuzztime=300s -parallel=1 -fuzz=FuzzLexer -v
This repository was put together afterexperimenting with a scripting language, anevaluation engine, putting together aFORTH-like scripting language, writing aBASIC interpreter and creatingyet another lisp..
I've also played around with a couple of compilers which might be interesting to refer to:
- Brainfuck compiler:
- A math-compiler:
Please feel free to open a new issuewith your example included so I can see how to fix it.
Steve
About
A simple/minimal TCL interpreter, written in golang