     [file version.texi not included]

This manual is for the LAC LISP Library (version VERSION).

Copyright © 2017 Gianluca Guida

     Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts.  A copy of the license is included in the section entitled ``GNU Free Documentation License''.

The LAC LISP Library Manual
***************************

This manual is for the LAC LISP Library (version VERSION.

Introduction
************

This manual is an introduction and a reference for the LAC LISP Library (LAC hereinafter).

LAC is a simple LISP implementation. Its interpreter is meant be embedded in your application (see Adding LAC to your program).

LAC is also extensible: you can add new atom types and execute your own functions written in lower level, compiled languages (see Extending the language).

For more information about the language itself, see The LAC Language.

Using LAC
*********

LAC is a library that implements a LISP interpreter with a system library that contains many useful functions to handle lists, symbols and integers.

The interpreter itself can be extended to add features, and this is the real power of LAC.

The rest of the chapter will introduce two common ways of using LAC: REPL extension and embedding. The difference between the two is that in the former the interpreter has control of the application, while in the latter the LISP interpreter can be called at will by the application to execute commands.

Please note that this chapter is just introductory. For a more in-depth discussion of the topic, see Adding LAC to your program.

REPL Extension
==============

Suppose you have a low-level library that implements some features in a specific domain, and you need a language capable of using those features to create small scripts, write prototypes, explore the library capabilities.

What you can do is to first use LAC to create a REPL (REPL stands for Read, Eval, Print Loop. It is used to describe the core functionality of an interpreter: reading an input, evaluating the value of the input and printing the calculated output value.) and then extend the LAC language with elements from your library.

Writing a REPL for LAC
----------------------

Writing a REPL in LAC is extremely simple. The C program in repl basic code produces an interactive command line REPL capable of executing LAC statements, e.g.:

     LAC>(+ 2 2)
     4

This will be essentially an interpreter for a basic LISP-like language, and you will be able to do integer, list and symbol processing with ease. You will also be able to create macros to extend the language to your needs. See The LAC Language.

Figure: A simple REPL for the LAC library

     #include <stdio.h>
     #include <readline/readline.h>
     #include <lac.h>

     int main (int argc, char *argv[])
     {
       lenv_t *null_env;

       /* Initialize LAC (create NULL environment) */
       null_env = lac_init();
       if (null_env == NULL)
         {
           fprintf(stderr, "Could not initialize lac");
           return -1;
         }

       /* REPL loop. */
       while (1)
         {
           char *buf;
           lreg_t res;

           /* Read an input line */
           buf = readline ("LAC>");
           if (buf == NULL)
             break;

           /* Evaluate S-Expressions. */
           res = sexpr_eval_string (buf, null_env);

           /* Print the result */
           sexpr_fprint(stdout, res);
           printf("\n");
         }

       /* Exit REPL */
       return 0;
     }

Extending the interpreter
-------------------------

The usefulness of LAC emerges when you add support for your own libraries to this language, and you can do this in two ways: adding Native Procedures and Atom Types.

Native Procedures
.................

Procedures in LISP-like languages are similar to what functions are in C. There are some major differences with C functions, for example in LAC procedures are first-class functions (This essentially means that a procedure (and its scope) can be treated as a value, passed as a parameter and returned by another procedure) and that they can be defined and modified at runtime.

A Native Procedure is a procedure written in a low level language, opaque to the interpreter (cannot be inspected or changed).  LAC defines a standard C interface for the low-level procedures, and functions to hook this function to symbols in the LISP machine.

Let's clarify the previous sentence with an example: the following C function is a Native Procedure.

     LAC_API static lreg_t
     proc_hello (lreg_t args, lenv_t * argenv, lenv_t * env)
     {
       fprintf(stdout, "Hello, World!");
       return NIL;
     }

It is a simple procedure that, ignoring all arguments passed, will always print to standard output the string ``Hello, World!'', and return the empty value NIL.

LAC_API is mostly needed to tell the compiler to follow certain rules (mostly alignment) that will ensure that it can be processed internally by the interpreter.

Adding this line to the code in repl basic code is not enough though to access it. We need to associate this function to a symbol, and this is called registering.

     /* PRE: lac_init() has already been
        called, and has returned null_env.  */
     lac_extproc_register (null_env, "hello", proc_hello);

This will hook the procedure defined above to the symbol HELLO. If we add to our code and run the REPL again, we will have a new command available in our interpreter. Note that symbols are case insensitive.

     LAC>HELLO
     <#LLPROC>
     LAC>(HELLO)
     Hello, World!()
     LAC>(hello)
     Hello, World!()
     LAC>

The function, as you can see above, first prints out to the screen the word ``Hello, World!'', and then returns, NIL, the void value of LISP, which is also the empty list, and this gets printed by the Print phase of the REPL as ().

To complete the example, we can change proc_hello to return a string instead of printing it to screen directly:

     LAC_API static lreg_t
     proc_hello(lreg_t args, lenv_t * argenv, lenv_t * env)
     {
       return lac_string_box("Hello, World!");
     }

If we register the above function, the REPL will return a string atom:

     LAC>(hello)
     "Hello, World!"
     LAC>

Adding Atom Types
.................

Embedding LAC
=============

The LAC Language
****************

The LAC System Library
======================

The LAC Library
***************

Extending the language
**********************

Adding LAC to your program
**************************

GNU Free Documentation License
******************************