From Rosetta Code
(Redirected from LIL)
This programming language may be used to instruct a computer to perform a task.
Official website
Garbage collected: No
Parameter passing methods: By value
Type safety: Safe
Type strength: Weak
Type expression: Implicit
Type checking: Dynamic

Listed below are all of the tasks on Rosetta Code which have been solved using LIL.

LIL is the Little Interpreted Language, a Tcl like scripting language. LIL is written by Kostas Michalopoulos, first released in 2010.

The implementation is in C, and meant for embedding in other applications. LIL also ships with a small interactive shell. Embedding can be via linked library or directly including lil.h and lil.c in builds.

Like Tcl, LIL uses a simple set of rules for parsing commands and arguments with everything treated as character data. Various types of substitutions provide extraordinary flexibility within the grammar rules.

Strings can be quoted with (using ") or without (using {}) dollar prefix and inner substitutions. Command substitutions are provided within [] markers.

The complete core language (for the 2019 release) is only about 3500 lines of C. The reference REPL interactive shell is implemented in just 200 lines of code (which includes registering a few new commands for things like system access from the shell).


<lang tcl>#

  1. Hello world in lil

print "Hello, world!"</lang>

The other LIL

From the author's readme.txt file:

As a side note, LIL has nothing to do with the "Little Implementation Language" for PDP (which i learned about months after i chose the name LIL for my library). Apparently that LIL was made during the same time as the UNIX system and the C language by P.J. Plauger. If you are interested in this historical language you can read about it here:


LIL is reflective. There is a reflect command that accepts a wide range of subcommands. These are useful both for exploring the language in the shell as well as providing a nice level of sophisticated script programming potentials.

prompt$ ./lil
Little Interpreted Language Interactive Shell
# reflect funcs
reflect info func rename unusedname quote set local write print puts eval
topeval upeval downeval enveval jaileval count index indexof filter list append
slice subst concat foreach return result expr inc incr dec read store if while
for char charat codeat substr strpos length trim ltrim rtrim strcmp streq
repstr split try error exit source lmap rand catcher watch writechar system

In the above list, writechar, system and readline are commands registered in the reference LIL shell.

reflect subcommands include:

     reflect version
       returns the LIL_VERSION_STRING
     reflect args <func>
       returns a list with the argument names for the given function
     reflect body <func>
       returns the code of the given function
     reflect func-count
       returns the number of the known functions
     reflect funcs
       returns a list with all the known function names
     reflect vars
       returns a list with all the known variable names (includes global
       and local variables)
     reflect globals
       returns a list with all the known global variable names

     reflect has-func <name>
       returns a true value (non-zero, non-empty value) if a function with
       the given name is known
     reflect has-var <name>
       returns a true value (non-zero, non-empty value) if a variable with
       the given name is known
     reflect has-global <name>
       returns a true value (non-zero, non-empty value) if a global
       variable with the given name is known
     reflect error
       returns the last error message or an empty string if there is no
       error condition active (this is usually used with the try function)

     reflect dollar-prefix [prefix]
       if [prefix] is specified, then this changes the dollar prefix.  If no
       arguments are given, the current dollar prefix is returned.  The dollar
       prefix is the command to be executed for dollar expansions (like $foo).
       The word after the dollar prefix is appended immediately after the
       prefix and the whole is executed.  The default dollar prefix is 'set '
       (notice the space which will separate the call to "set" from the word

     reflect this
       returns the code of the current local environment.  This will return
       the currently executed function's body, the current root (top-level)
       code or the current catcher code (if the current environment is a
       catcher environment)

     reflect name
       returns the name of the currently executed function or an empty string
       if the code is executed at root level (or the name of the current
       function is unknown)


LIL includes catcher blocks which can be used to provided lazy loading of Domain Specific Language commands, as well as high level error trapping. There is also a try command for more localized exception handling.

<lang tcl>#

  1. Test for the 'catcher' function. The catcher function can be used to call
  2. some code when an unknown function is called so that the script can 'catch'
  3. unknown calls. It can be used to implement shell-like behavior or write small
  4. mini/local languages for a specific purpose.
  1. Set a catcher that will print the command and its arguments. The catcher will
  2. receive the command and arguments in an 'args' list, like if an anonymous
  3. function without arguments was specified.

print "Catcher test 1"

catcher {

   print "catcher: $args"


  1. Try some commands

print "This will be printed just fine" foo bar etc this will not be printed however substitution is still done [expr 3 + 3] "since a list is what is displayed, this will appear in braces"

  1. Define a set of functions which define a mini language. The catcher is used
  2. to delegate the call to the proper function. In this example the functions
  3. just print what they do. The catcher is only set temporary from the parsecfg
  4. function (which is supposed to parse some sort of configuration script) and
  5. reset to the previous catcher before the function ends.

print "Catcher test 2"

set level 0

func print-level {} {

   for {set i 0} {$i < $level} {inc i} {write "  "}


func add-field {name values} {

   set previous-field $last-field
   set global last-field $name
   print "Adding field $last-field"
   inc level
   eval $values
   dec level
   set global last-field $previous-field


func set-attribute {name value} {

   print "Adding attribute '${name}' with value '${value}' to the field $last-field"


func parsecfg {cfg} {

   set prev_catcher [catcher]
   catcher {
       set name [index $args 0]
       set value [index $args 1]
       if [streq [charat $name 0] .] {
           set-attribute $name $value
       } {
           add-field $name $value
   eval $cfg
   catcher $prev_catcher


print "We'll try to parse"

parsecfg {

   user {
       .name "Kostas Michalopoulos"
       .www none
       .nick "Bad Sector"
       groups {
           .group coder
           .group maintainer
       .flags [expr 3 + 3 + 0]         # this will be parsed as ".flags 6"
   groups {
       group {
           .name coder
           .info "LIL Coders"
           .cando stuff
       group {
           .name maintainer
           .info "LIL Maintainers"
           .cando otherstuff


Done # The previous catcher will be restored so this will display "Done!"

  1. Remove catchers, etc. An empty string will remove the current catcher and
  2. lil will report unknown function calls like previously (

print "Catcher test 3"

catcher {}

"This will fail" And this will never be executed</lang>


Many of the lower level operations in LIL can be extended in an application via hooks provided by LIL_CALLBACK_xxxx routines.


Based on Tcl style command handling, LIL supports substitutions for strings and command evaluations.

The dollar-prefix variable substitutions normally seen in Tcl and other languages can be customized to call a user defined function at runtime.

<lang tcl>

  1. Test for "reflect dollar-prefix"
  1. Set some variable

set foo bar

  1. Use dollar expansion with the default prefix ('set ')

print $foo

  1. Define a custom set-like function which prints the variable in question

func my-set {name} {

   print "Requested the value of [set name]"
   return [set [set name]]


  1. Try it

print [my-set foo]

  1. Now use reflect dollar-prefix to report and change the prefix

print "Current dollar-prefix: '[reflect dollar-prefix]'" reflect dollar-prefix {my-set } print "New dollar prefix: '[reflect dollar-prefix]'"

  1. Try using the new dollar prefix

print $foo</lang>

prompt$ ./lil dollar.lil
Requested the value of foo
Current dollar-prefix: 'set '
New dollar prefix:     'my-set '
Requested the value of foo