Design: Embedding Lua in script
In this article, we describe the initial design of lscript
and how we can modify it to
embed a programming language.
The design of lscript
The C code for lscript
uses interposition to forward and log shell I/O. The code uses
some helper functions to perform the forwarding. Specifically:
- When
lscript
receives user input, it sends the input to the underlying program by passing the input to thewritetosubprocess
function. -
When
lscript
receives program output, it:- sends the output to the user by passing the output to the
writetouser
function - writes the output to a log file by passing the output to the
writetolog
function
- sends the output to the user by passing the output to the
In general, anything intended for the the underlying program goes through
writetosubprocess
; anything coming from the underlying program goes through
writetouser
and writetolog
.
The goal of this assignment is to make lscript
more extensible by embedding the Lua
programming language within it. As part of the embedding, the normal forwarding logic we
just described will be rewritten so that it is handled by a separate (and replaceable!),
interpreted program.
Why Lua?
Typically, the languages most amenable to embedding are “scripting languages”. Scripting
languages that support embedding in C programs include Python, Perl, Ruby, JavaScript,
Lua, and numerous others. But some are more amenable to the task than others. Python,
Perl, and Ruby are large (for example, the Python interpreter is over 100 times the size
of the lscript
program), are typically not written with ease of embedding foremost,
and are not actually very fast interpreters (which may not matter for our example, but
might in some other program). Modern JavaScript implementations can be quite fast, but
often even larger (e.g., 200 times the size of the lscript
program).
In contrast, Lua is compact, relatively speedy for an interpreter, and was designed to be easy to embed. Unlike some other languages that claim to be designed for ease of embedding, Lua is small without being hard to program or lacking in expressiveness.
Redesigning lscript
to embed Lua
The version of lscript
with embedding will modify the lscript
interposition in the
following way:
- When
lscript
receives user input, it sends the input to a Lua functionuserInputEvent
. - When
lscript
receives program output, it sends the input to a Lua functionsubprocessOutputEvent
.
These two Lua functions can do whatever we want. You are given a default script where
userInputEvent
just passes its input unmodified to the C function writetosubprocess
,
and where subprocessOutputEvent
passes its input to both C functions writetouser
and
writetolog
. This just replicates the original behavior of the program. But now we have
the flexibility to change the “brains” of the code without recompiling the C code, just
by editing the Lua script and restarting the program.