home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 4
/
FreshFish_May-June1994.bin
/
bbs
/
may94
/
util
/
edit
/
jade.lha
/
Jade
/
src
/
lispcmds.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-19
|
49KB
|
2,015 lines
/* lispcmds.c -- Lots of standard Lisp functions
Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
This file is part of Jade.
Jade is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Jade is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jade; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "jade.h"
#include "jade_protos.h"
#include <string.h>
_PR void lispcmds_init(void);
_PR VALUE sym_load_path;
VALUE sym_load_path, sym_lisp_lib_dir;
/*
::doc:load_path::
A list of directory names. When `load' opens a lisp-file it searches each
directory named in this list in turn until the file is found or the list
is exhausted.
::end::
::doc:lisp_lib_dir::
The name of the directory in which the standard lisp files live.
::end::
*/
_PR VALUE cmd_quote(VALUE);
DEFUN("quote", cmd_quote, subr_quote, (VALUE args), V_SF, DOC_quote) /*
::doc:quote::
(quote ARG) <SPECIAL-FORM>
'ARG
Returns ARG.
::end:: */
{
if(CONSP(args))
return(VCAR(args));
return(NULL);
}
_PR VALUE cmd_function(VALUE);
DEFUN("function", cmd_function, subr_function, (VALUE args), V_SF, DOC_function) /*
::doc:function::
(function ARG) <SPECIAL-FORM>
#'ARG
Normally the same as `quote'. When being compiled, if ARG is not a symbol
it causes ARG to be compiled as a lambda expression.
::end:: */
{
if(CONSP(args))
return(VCAR(args));
return(NULL);
}
_PR VALUE cmd_defmacro(VALUE);
DEFUN("defmacro", cmd_defmacro, subr_defmacro, (VALUE args), V_SF, DOC_defmacro) /*
::doc:defmacro::
(defmacro NAME LAMBDA-LIST [DOC-STRING] BODY...)
Defines a macro called NAME with argument spec. LAMBDA-LIST, documentation
DOC-STRING (optional) and body BODY. The actual function value is
`(macro lambda LAMBDA-LIST [DOC-STRING] BODY...)'
Macros are called with their arguments un-evaluated, they are expected to
return a form which will be executed to provide the result of the expression.
A pathetic example could be,
(defmacro foo (x) (list 'cons nil x))
=> foo
(foo 'bar)
=> (nil . bar)
This makes `(foo X)' a pseudonym for `(cons nil X)'.
Note that macros are expanded at *compile-time* (unless, of course, the Lisp
code has not been compiled).
::end:: */
{
if(CONSP(args))
return(cmd_fset(VCAR(args), cmd_cons(sym_macro, cmd_cons(sym_lambda, VCDR(args)))));
else
return(NULL);
}
_PR VALUE cmd_defun(VALUE);
DEFUN("defun", cmd_defun, subr_defun, (VALUE args), V_SF, DOC_defun) /*
::doc:defun::
(defun NAME LAMBDA-LIST [DOC-STRING] BODY...)
Defines a function called NAME with argument specification LAMBDA-LIST,
documentation DOC-STRING (optional) and body BODY. The actual function
value is,
`(lambda LAMBDA-LIST [DOC-STRING] BODY...)'
::end:: */
{
if(CONSP(args))
return(cmd_fset(VCAR(args), cmd_cons(sym_lambda, VCDR(args))));
else
return(NULL);
}
_PR VALUE cmd_car(VALUE);
DEFUN("car", cmd_car, subr_car, (VALUE cons), V_Subr1, DOC_car) /*
::doc:car::
(car CONS-CELL)
Returns the value stored in the car slot of CONS-CELL, or nil if CONS-CELL
is nil.
::end:: */
{
if(CONSP(cons))
return(VCAR(cons));
return(sym_nil);
}
_PR VALUE cmd_cdr(VALUE);
DEFUN("cdr", cmd_cdr, subr_cdr, (VALUE cons), V_Subr1, DOC_cdr) /*
::doc:cdr::
(cdr CONS-CELL)
Returns the value stored in the cdr slot of CONS-CELL, or nil if CONS-CELL
is nil.
::end:: */
{
if(CONSP(cons))
return(VCDR(cons));
return(sym_nil);
}
_PR VALUE cmd_list(VALUE);
DEFUN("list", cmd_list, subr_list, (VALUE args), V_SubrN, DOC_list) /*
::doc:list::
(list ARGS...)
Returns a new list with members ARGS...
::end:: */
{
return(args);
}
_PR VALUE cmd_copy_list(VALUE);
DEFUN("copy-list", cmd_copy_list, subr_copy_list, (VALUE list), V_Subr1, DOC_copy_list) /*
::doc:copy_list::
(copy-list LIST)
Returns a new list which is identical to LIST except that the cons cells
which it is made from are different, all elements are shared however.
::end:: */
{
VALUE res = sym_nil;
VALUE *last = &res;
while(CONSP(list))
{
if(!(*last = cmd_cons(VCAR(list), sym_nil)))
return(NULL);
last = &VCDR(*last);
list = VCDR(list);
}
return(res);
}
_PR VALUE cmd_make_list(VALUE, VALUE);
DEFUN("make-list", cmd_make_list, subr_make_list, (VALUE len, VALUE init), V_Subr2, DOC_make_list) /*
::doc:make_list::
(make-list LENGTH [INITIAL-VALUE])
Returns a new list with LENGTH members, each of which is initialised to
INITIAL-VALUE, or nil.
::end:: */
{
int i;
VALUE res = sym_nil;
VALUE *last;
DECLARE1(len, NUMBERP);
last = &res;
for(i = 0; i < VNUM(len); i++)
{
if(!(*last = cmd_cons(init, sym_nil)))
return(NULL);
last = &VCDR(*last);
}
return(res);
}
_PR VALUE cmd_append(VALUE);
DEFUN("append", cmd_append, subr_append, (VALUE args), V_SubrN, DOC_append) /*
::doc:append::
(append LISTS...)
Non-destructively concatenates each of it's argument LISTS... into one
new list which is returned.
::end:: */
{
VALUE res = sym_nil;
VALUE *resend = &res;
while(CONSP(args))
{
if(CONSP(VCAR(args)))
*resend = copylist(VCONS(args)->cn_Car);
else
*resend = VCAR(args);
while(CONSP(*resend))
resend = &(VCDR(*resend));
args = VCDR(args);
}
return(res);
}
_PR VALUE cmd_nconc(VALUE);
DEFUN("nconc", cmd_nconc, subr_nconc, (VALUE args), V_SubrN, DOC_nconc) /*
::doc:nconc::
(nconc LISTS... )
Destructively concatenates each of it's argument LISTS... into one new
list. Every LIST but the last is modified so that it's last cdr points
to the beginning of the next list. Returns the new list.
::end:: */
{
VALUE res = sym_nil;
VALUE *resend = &res;
while(CONSP(args))
{
VALUE tmp = VCAR(args);
if(CONSP(tmp))
{
*resend = tmp;
while(CONSP(VCDR(tmp)))
tmp = VCDR(tmp);
resend = &VCDR(tmp);
}
args = VCDR(args);
}
return(res);
}
_PR VALUE cmd_rplaca(VALUE, VALUE);
DEFUN("rplaca", cmd_rplaca, subr_rplaca, (VALUE cons, VALUE car), V_Subr2, DOC_rplaca) /*
::doc:rplaca::
(rplaca CONS-CELL NEW-CAR)
Sets the value of the car slot in CONS-CELL to NEW-CAR. Returns the new
value.
::end:: */
{
DECLARE1(cons, CONSP);
VCAR(cons) = car;
return(car);
}
_PR VALUE cmd_rplacd(VALUE, VALUE);
DEFUN("rplacd", cmd_rplacd, subr_rplacd, (VALUE cons, VALUE cdr), V_Subr2, DOC_rplacd) /*
::doc:rplacd::
(rplacd CONS-CELL NEW-CDR)
Sets the value of the cdr slot in CONS-CELL to NEW-CAR. Returns the new
value.
::end:: */
{
DECLARE1(cons, CONSP);
VCDR(cons) = cdr;
return(cdr);
}
_PR VALUE cmd_reverse(VALUE);
DEFUN("reverse", cmd_reverse, subr_reverse, (VALUE head), V_Subr1, DOC_reverse) /*
::doc:reverse::
(reverse LIST)
Returns a new list which is a copy of LIST except that the members are in
reverse order.
::end:: */
{
VALUE res = sym_nil;
while(CONSP(head))
{
VALUE new;
if(!(new = cmd_cons(VCAR(head), res)))
return(NULL);
head = VCDR(head);
}
return(res);
}
_PR VALUE cmd_nreverse(VALUE);
DEFUN("nreverse", cmd_nreverse, subr_nreverse, (VALUE head), V_Subr1, DOC_nreverse) /*
::doc:nreverse::
(nreverse LIST)
Returns LIST altered so that it's members are in reverse order to what they
were. This function is destructive towards it's argument.
::end:: */
{
VALUE res = sym_nil;
VALUE nxt;
if(!CONSP(head))
return(sym_nil);
do {
if(CONSP(VCDR(head)))
nxt = VCDR(head);
else
nxt = NULL;
VCDR(head) = res;
res = head;
} while((head = nxt));
return(res);
}
_PR VALUE cmd_assoc(VALUE, VALUE);
DEFUN("assoc", cmd_assoc, subr_assoc, (VALUE elt, VALUE list), V_Subr2, DOC_assoc) /*
::doc:assoc::
(assoc ELT ASSOC-LIST)
Searches ASSOC-LIST for a list whose first element is ELT. `assoc' uses
`equal' to compare elements. Returns the sub-list starting from the first
matching association.
::end:: */