SketchyLISP Reference |
Copyright (C) 2007 Nils M Holm |
[<<Library Functions] | [Contents] [Index] | [Differences to Scheme>>] |
7.1 Embedding the Interpreter
7.2 Initialization and Shutdown Functions
7.3 Evaluation Functions
7.4 Error Handling Functions
7.5 Access Functions
7.6 Input/Output Functions
7.7 Metric Functions
7.8 User Procedure Functions
7.9 Construction Functions
7.10 Miscellaneous Functions
7.11 Variables
7.12 Constants
The SketchyLISP interpreter consists of two parts: the sketchy.h header file and the library. The header contains
The library contains the interpreter itself. To compile a C program that interfaces SketchyLISP, use the following invocation:
cc program.c -lsketchy
You might have to add -Iincdir and -Llibdir options, if the header or library are located in non-standard places.
A minimal program embedding the SketchyLISP interpreter follows. The program implements a complete interpreter shell. The only differences to the `real' SketchyLISP shell are that this simple application does not implement meta commands, batch mode, signal handling, or command line options.
#include <stdio.h> #include <sketchy.h> void main(void) { int n; if (sk_init(SK_DFL_NODES, SK_DFL_VCELLS)) { fprintf(stderr, "sk_init failed\n"); exit(1); } if (sk_loadImage(SK_DFL_IMAGE)) { fprintf(stderr, "sk_loadImage failed\n"); exit(1); } while (1) { SK_errFlag = 0; n = sk_read(); if (n == sk_eof()) break; n = sk_eval(n); if (SK_errFlag) { sk_printError(); } else { sk_pr("=> "); sk_print(n); sk_nl(); } } sk_bye(); }
The functions, variables, and constants used in this program will be explained in detail in the following sections.
void sk_bye(void);
Shut down SketchyLISP and terminate the calling program using exit(0).
void sk_fini(void);
Release the memory pools allocated by sk_init().
int sk_init(int nodes, int vcells);
Initialize the interpreter and allocate the memory pools. Return a value indicating success (0) or failure (<0). The arguments nodes and vcells indicate the numbers of nodes and vector cells to allocate. To allocate a default number of resources, use
sk_init(SK_DFL_NODES, SK_DFL_VCELLS);
Neither the number of nodes nor the number of vcells may be less than SK_MIN_SIZE.
The release date of the interpreter can be found in the constant SK_RELEASE and the major version number in SK_MAJOR. The release date has the format "yyyy-mm-dd", the version number is an integer.
int sk_eval(int n);
Evaluate the SketchyLISP node n and return a node representing the normal form of n. This function sets SK_errFlag in case of an error. In this case, the return value of sk_eval() is undefined.
Sk_eval() can trigger a garbage collection. See sk_protect() for details.
The node returned by sk_eval() is unprotected.
void sk_gotError(void);
Signal the interpreter that the most recent error has been handled. Either this routine or sk_printError must be called after detecting an error condition. Otherwise the interpreter will not evaluate any further expressions.
void sk_printCallTrace(int frame);
Print a trace of those 10 functions that were most recently called.
void sk_printError(void);
Print an error message and reset the error condition by calling sk_gotError(). If the error flag (SK_errFlag) is clear upon entry, sk_printError() does not print any message. If it does print a message, it has the following form:
* file: line: function: message: expr * additional information
File is the file containing the source of the error. It is taken from the variable SK_errFile. If this variable is NULL, the file part is omitted.
Line is the line number of the expression that has caused the error. It is equal to the value of SK_errLine.
Function is the name of the function in which the error occured. It is taken from the node SK_errFun. If this node is NIL, sk_printError() prints REPL instead.
Message is the error message itself (SK_errMsg).
Expr is the expression that caused the error. It is taken from the node SK_errExpr. If SK_errExpr is equal to the constant SK_NOEXPR, the error was not caused by any specific expression.
The additional information part is equal to the SK_errArg variable. It prints only, if this variable is not NULL.
If the SK_errFrame variable is not NIL, sk_printError() also prints a call trace using sk_printCallTrace().
void sk_stop(void);
Stop the interpreter by issuing an error. The error message delivered to the interpreter is "interrupted". After stopping the interpreter using sk_stop(), the error condition must be reset by issuing sk_printError() or sk_gotError().
sk_stop() is typically called by a signal handler. The following code fragment would handle keyboard interrupts (SIGINT) under Unix:
#include <signal.h> void catchIntr(int sig) { sk_stop(); } void main(void) { signal(SIGINT, catchIntr); /* * Place your SketchyLISP interface here. */ }
int sk_car(int n);
Extract the car part of the node n.
int sk_cdr(int n);
Extract the cdr part of the node n.
int sk_eof(void);
Return the EOF object. Comparing a node with the EOF object
resembles the eof-object?
primitive:
int eof_object(int n) { return n == sk_eof(); }
int sk_false(void);
Return the node representing logical falsity (aka #f
).
long sk_int(int n, int *ep);
Return the value of the big integer node n. If n is not the root of an integer node or the value of the node is too big to fit in a long int, return 0 and set ep[0] to a non-zero value.
The caller must set ep[0] to zero before calling sk_int().
const int sk_nil(void);
Return the node representing the empty list (aka NIL).
const char *sk_string(int n);
Return the value of the string node n. If n is not the root of an string node, return NULL.
int sk_true(void);
Return the node representing logical truth (aka #t
).
int sk_void(void);
Return the node representing no value (aka #<void>
).
int sk_writeToString(int n);
Write the external representation of the node n to a string object and return it. Use the sk_string() function to access the text of the string returned by sk_writeToString().
Sk_writeToString() can trigger a garbage collection. See sk_protect() for details.
The node returned by sk_writeToString() is unprotected.
void sk_display(int n);
Display the SketchyLISP node n using the
display
primitive.
int sk_load(char *p);
Load a source file by temporarily redirecting the input stream to the file p. Return a value indicating success (0) or failure (<0). Failure occurs, if the source file could not be opened or contains an erroneous expression. In the latter case, some definitions contained in the file may have loaded sucessfully.
Sk_load() can trigger a garbage collection. See sk_protect() for details.
void sk_nl(void);
Write a newline sequence to the output stream.
void sk_pr(char *s);
Write the string s to the output stream.
void sk_print(int n);
Write the external representation of the SketchyLISP node n to the output stream.
void sk_prnum(int n, int w);
Print the number n. If n has less than w digits, pad the output to w characters using blanks. W may not be larger than 7.
int sk_rdch(void);
Read a single raw character from the input stream of the interpreter and return it. When the input stream is exhausted, return SK_EOT.
The character may be put back to the input stream using sk_reject().
int sk_read(void);
Read a Scheme datum from the input stream and convert it to
internal representation. Return a SketchyLISP node representing the
internal form. This function resembles the read
primitive.
Sk_read() can trigger a garbage collection. See sk_protect() for details.
The node returned by sk_read() is unprotected.
int sk_reject(int c);
Put the character c back to the input stream. The next character read by the interpreter (or by sk_rdch()) will be exactly this character.
Only one single character may be rejected. Rejecting multiple characters before reading them will result in the loss of all but the most recently rejected character.
void sk_require(char *p);
Load the content of the file p using sk_load, but only if the basename of p is not bound in the interpreter. The basename of a path is the element between the last slash (if any) and the first dot (if any):
/this/is/some/path/basename.scm
Sk_require() can trigger a garbage collection. See sk_protect() for details.
void sk_count(struct sk_counter *c, int k);
Increment the counter c by some small amount k (k may not be larger than 1000). If the counter overflows, an error condition occurs. The counter structure is defined as follows:
struct sk_counter { int n, /* ones */ n1k, /* thousands */ n1m, /* millions */ n1g; /* billions */ };
void sk_printCounter(struct sk_counter *c);
Write the value of a counter to the output stream. For a definition of the sk_counter structure, see sk_count(). The counter value is printed in groups of three digits separated by commas, like this:
1,234,567
void sk_printStats(void);
Print some statistics of the form
nr reduction steps nn nodes allocated ng garbage collections
where nr = SK_reductions,
nn = SK_allocations,
and ng =
SK_collections.
All the statistics variables are of the type sk_counter. For its definition, see sk_count(). Individual values are printed using sk_printCounter().
int sk_resetCounter(struct sk_counter *c);
Reset the counter c to zero. For a definition of the sk_counter structure, see sk_count().
int sk_addUserPrim(char *name, int (*handler)(int n));
Register a handler for a user procedure. Name names the procedure and handler is the function handling calls to that procedure.
The following foo() handler implements a user procedure that divides an integer by two:
int foo(int n) { int m; int e; long v; if (sk_args(n) != 1) return sk_error("foo: wrong number of args", n); m = sk_nthArg(n, 0); if (sk_typeof(m) != SK_TYPE_INTEGER) return sk_error("foo: not an integer", m); e = 0; v = sk_int(m, &e); if (e) return sk_error("foo: value too big", m); return sk_mkInteger(v/2); }
The following call to sk_addUserPrim registers the procedure:
sk_addUserPrim("foo", foo);
After registering the procedure, it can be called by SketchyLISP programs in the same way as primitive functions and lambda functions:
(foo 123) => 61
Sk_addUserPrim() can trigger a garbage collection. See sk_protect() for details.
int sk_args(int n);
Return the number of actual arguments passed to a user procedure.
N is the node received by the function implementing the procedure.
int sk_error(char *msg, int n);
Report an error that occurred in a user procedure. Msg is the error message and n is the expression or part of the the expression that caused the error.
int sk_nthArg(int n, int i);
Return a node representing the i'th actual argument passed to a user procedure.
N is the node received by the function implementing the procedure.
void sk_protect(int n);
Protect the node n during garbage collections. Protected nodes will never be reclaimed.
Protected nodes must be released using sk_unprotect() before returning from a user procedure.
int sk_typeof(int n);
Return the type of the node n.
Types are encoded using the following constants:
SK_TYPE_BOOLEAN SK_TYPE_CHAR SK_TYPE_EOF SK_TYPE_INTEGER SK_TYPE_PAIR SK_TYPE_PROCEDURE SK_TYPE_STRING SK_TYPE_SYMBOL SK_TYPE_SYNTAX SK_TYPE_VOID
void sk_unprotect(int k);
Unprotect the most recently protected nodes. K is the number of nodes to unprotect.
int sk_cons(int car, int cdr);
Create a fresh node with car=car and cdr=cdr. Car and cdr are nodes.
Sk_cons() can trigger a garbage collection. See sk_protect() for details.
The node returned by sk_cons() is unprotected.
int sk_mkChar(int c);
Create a fresh char node representing the character c.
Sk_mkChar() can trigger a garbage collection. See sk_protect() for details.
The node returned by sk_mkChar() is unprotected.
int sk_mkInteger(long v);
Create a fresh integer node representing the value v.
Sk_mkInteger() can trigger a garbage collection. See sk_protect() for details.
The node returned by sk_mkInteger() is unprotected.
int sk_mkString(char *s, int k);
Create a fresh string node representing the value s. K must specify the number of characters in the string s (excluding the delimiting NUL).
Sk_mkString() can trigger a garbage collection. See sk_protect() for details.
The node returned by sk_mkString() is unprotected.
int sk_readFromString(char *s);
Read the string s in the same way as the
read-from-string
primitive and return a node
pointing to the internal representation of a singleton list
containing the form read.
In case s does not contain a well-formed expression, return sk_false().
Sk_readFromString() can trigger a garbage collection. See sk_protect() for details.
The node returned by sk_readFromString() is unprotected.
int sk_setCar(int n, int new);
Set the car part of the node n to new. N must be a pair node, new may be a node of any type.
int sk_setCdr(int n, int new);
Set the cdr part of the node n to new. N must be a pair node, new may be a node of any type.
void sk_dumpImage(char *p);
Dump the workspace of the interpreter to the file p. This function sets SK_errFlag in case of an error.
void sk_dumpSymbols(char *p);
Write a list of packages and the symbols of the package p to the output stream.
void sk_findSource(char *p, char *buf);
Attempt to locate the file p in "." and in all directories specified in the SKETCHYSRC emvironment variable. If the file has no suffix try both the file name and the file name with ".scm" appended. Return the full path of the file upon success and NULL in case the file could not be located.
The buf array must be at least SK_MAXPATHL characters long.
sk_findSource() is used by require
to
locate source files.
void sk_gc(struct sk_gcStats *stats);
Perform a garbage collection and fill the stats data structure with some statistics. stats is defined as follows:
struct sk_gcStats { int nodes_used, vcells_used, nodes_max, vcells_max; };
The _used fields are filled with the numbers of nodes and vcells currently used, and the _max fields are filled with peak load of the memory pools since the last call to sk_gc.
sk_gc also resets the peak load indicators.
Sk_gc() will trigger a garbage collection. See sk_protect() for details.
char **sk_license(void);
Return a pointer to the conditions of use as an array of strings. Each string contains one line of the license. The last line contains NULL.
int sk_loadImage(char *p);
Load a workspace image from the file p. Return a value indicating success (0) or failure (<0). Possible causes for failure are:
Note: After a failed attempt to load an image, the interpreter must be shut down by calling sk_fini() and then re-initialized using sk_init().
extern struct sk_counter SK_allocations;
Allocation counter. See sk_count().
extern int SK_arrowMode;
Set arrow mode. See :arrow-mode
meta command.
extern int SK_closureForm;
External representation of procedures (0,1,2). See
:closure-form
meta command.
extern struct sk_counter SK_collections;
Garbage collection counter. See sk_count().
extern char SK_errArg[SK_TEXTLEN];
Additional error information. See sk_printError().
extern int SK_errExpr;
Expression causing last error. See sk_printError().
extern char SK_errFile[SK_MAXPATHL];
File of last error. See sk_printError().
Error flag. See sk_eval(), sk_printError(), and sk_gotError().
extern int SK_errFlag;
extern int SK_errFrame;
Call frame of last error. See sk_printError() and sk_printCallTrace().
extern int SK_errFun;
Function of last error. See sk_printError().
extern int SK_errLine;
Line number of last error. See sk_printError().
extern char *SK_errMsg;
Most recent error message. See sk_printError().
extern int SK_metaChar;
Meta command character. Prefix for meta commands. Default: ':'.
extern struct sk_counter SK_reductions;
Reduction counter. See sk_count().
extern int SK_statFlag;
Statistics flag. Start gathering statistics. See
sk_printStats() function and :statistics
meta
command.
extern int SK_strictApply;
Strict (R5RS) apply flag. See :r5rs-apply
meta command.
extern int SK_trace;
Function being traced. See :trace
meta command.
extern int (*SK_traceHandler)(int n);
Pointer to used-defined trace handler. Set to NULL to use the internal trace handler. For now, see the source code (sketchy.c)for further details.
#define SK_DFL_IMAGE "/usr/local/share/sketchy/sketchy.image"
The full path name of the default image.
#define SK_DFL_NODES 131072
The default size of the node pool.
#define SK_DFL_NODES SK_DFL_NODES
The default size of the vector cell pool.
#define SK_EOT -1
The end of input indicator of the sk_rdch() function. To test for the end of interpreter input, compare against sk_eof().
#define SK_MAJOR 99
The major version number of the current release (probably not 99). Used to identify image files.
#define SK_MAXPATHL 256
The maximum length of a path name.
#define SK_MAX_USER_PRIMITIVES 64
The maximum number of user procedures.
#define SK_MIN_SIZE 12288
The minimum size of the node pool and vector pool.
#define SK_NOEXPR -1
Pass this constant to sk_error() to indicate that an error is not related to a specific expression.
#define SK_RELEASE "2006-09-23"
The date of the current release.
#define SK_TEXTLEN 1024
The maximum size of textual objects like string literals, numeric literals, symbols, etc.
[<<Library Functions] | [Contents] [Index] | [Differences to Scheme>>] |