Commit b0ce08d0 authored by jjgarcia's avatar jjgarcia

Changes towards 0.7b comprise naming and calling conventions. See CHANGELOG.

parent 99cea6f7
Announcement of ECL v0.7
Announcement of ECL v0.7b
=========================
ECL stands for Embeddable Common-Lisp. The ECL project is an effort to
......@@ -10,66 +10,106 @@ ECL is currently hosted at SourceForge. The home page of the project
is http://ecls.sourceforge.net, and in it you will find source code
releases, a CVS tree and an up to date documentation.
ECL 0.7
=======
Notes for this release
======================
* Errors fixed:
The names of many functions have changed. The global variables which
held pointers to symbols and keywords have disappeared. But the most
important change is the change on the calling conventions. Now there
are two types of C functions which the Lisp environment recognizes
1) Functions with a fixed number of arguments
cl_object my_function(cl_object arg1, cl_object arg2)
They are passed to the lisp environment using cl_def_c_function()
and cl_make_cfun(). They take a fixed number of arguments and the
interpreter checks this for them
2) Functions with optional and keyword arguments
cl_object my_function(int narg, ...)
They get a variable number of arguments, given by "narg". They should
check this and signal an error if needed. They are manipulated using
cl_def_c_function_va() and cl_make_cfun_va().
See below for a list of changes (And read src/h/external.h,
src/c/cfun.d, src/c/eval.d if you want :-)
- When installing, ECL would not build all required directories.
ECL 0.7b
========
- Symbol BUILD-PROGRAM should be exported from package C.
* Errors fixed:
- In compiled code UNWIND-PROTECT would procted also the exit form,
resulting in an infinite loop when the exit form fails.
- SI::BC-DISASSEMBLE would not use Lisp streams for output.
* System design:
- Global variables READsuppress, READdefault_float_format,
READtable, and READbase have been removed. The corresponding
special variables are used instead.
- No need for function read_object_recursive(), since read_object()
is equivalent to it.
- Changed the algorithm of the list reader. A dot which is not
escaped is read as a symbol SI::. which is recognized by
LEFT-PARENTHESIS-READER. This avoids using global variables
"in_list_flag" and "dot_flag".
- The calling conventions have been changed. SI::C-ARGUMENTS-LIMIT
and LAMBDA-PARAMETERS-LIMIT are both 64. Up to C-ARGUMENTS-LIMIT
may be passed to a function using C calling conventions. If the
function is to retrieve more arguments, (for instance through a
&rest variable), this can be done, but then the arguments have to
be pushed on the lisp stack. This method allows us to raise the
CALL-ARGUMENTS-LIMIT up to MOST-POSITIVE-FIXNUM. From a users
point of view, there is no visible change, excep the fact that a
function may receive more &optional, &key and &rest arguments.
- The function apply() has been replaced with cl_apply_from_stack().
The former took a pointer to the list of arguments. The latter
assumes that the last "narg" elements on the lisp stack are the
arguments of the function.
- Setting a (DECLARE (SI::C-LOCAL)) inside a function, we advise the
compiler to make it local to an object file and do not export it
for general use outside this file, neither as C code nor in Lisp.
* Visible changes:
- New function cl_defvar() implements DEFVAR.
- New functions SI:SAFE-EVAL and cl_safe_eval() allow the user to
evaluate code with errors without jumping into the
debugger. Useful when embedding ECL in other programs.
- Global variable si::*cblock* keeps a pointer to the descriptor of the
library being loaded (on systems which support DLLs).
- New function SI:OPEN-UNIX-SOCKET-STREAM creates a two-way stream
attached to a unix socked (Unix sockets are pipes which programs
from the same computer may use to communicate with each other, and
they are either anonymous (not supported by ECL) or associated to
a file of the filesystem).
* Visible changes:
- New function SI:LOOKUP-HOST-ENTRY encompasses the C calls
gethostbyname() and gethostbyaddress() and it is used to guess the
address, aliases and hostname of a machine in the Internet (Currently
we only support AF_INET protocol).
- The C counterparts of the Lisp functions have now the prefix
cl_*. For instance, LIST-LENGTH is named cl_list_length(). There
are two types of functions. Those who take a fixed number of
arguments, are just called using C calling conventions:
cl_object form = c_string_to_object("(1 2 3 4)");
cl_object l = cl_list_length(form);
But there are functions which take a variable number of arguments:
in this case, the first argument must be the total number of
arguments. For instance
cl_object form = cl_read(0);
or
cl_object form = cl_read(1, Cnil);
- Renamed functions MF() and MM() to cl_def_c_function(),
cl_def_c_function_va() and cl_def_c_macro_va(). Removed
make_function() and make_si_function(), which had a more limited
purpose. The *_va() functions take as argument a C function with
prototype
cl_object (*function)(int narg, ...)
which means that the function should accept any number of
arguments and signal an error when the number is incorrect. The
functions without *_va() suffix, take as argument a C function
with prototype
cl_object (*function)()
and an integer "narg" denoting the number of arguments that this
function actually receives.
- Within the debugger, users are now able to evaluate expressions using the
lexical environment of the functions being debugged. Sample session:
> (defun foo (x) (cos x))
FOO
> (foo 'a)
A is not of type NUMBER.
Broken at COS.
>> :b
Backtrace: COS > foo > eval
>> :p
Broken at FOO.
>> :v
Block names: FOO.
Local variables:
X: A
>> (return-from foo (cos 2.0))
-0.4161468
- DISASSEMBLE can now either disassemble the bytecodes of an interpreted
function, or translate a lisp expression into C and show the result.
- New program "ecl-config" outputs either the flags compile ("ecl-config -c")
or to link ("ecl-config -l") a program using the ECL library.
- In compiled code, constants which are EQUALP are merged; that is, they
become EQ at run time.
- cl_special_form_p() renamed to cl_special_operator_p().
* ANSI compatibility:
- READ and READ-PRESERVING-WHITESPACE behave the same when
RECURSIVE-P is NIL. Furthermore, EOF is detected when EOF-ERROR-P
is true, regardless of the value of RECURSIVE-P.
- DEFINE-SYMBOL-MACRO finally implemented.
......@@ -1016,6 +1016,86 @@ ECL 0.7
RECURSIVE-P is NIL. Furthermore, EOF is detected when EOF-ERROR-P
is true, regardless of the value of RECURSIVE-P.
ECL 0.7b
========
* Errors fixed:
- SI::BC-DISASSEMBLE would not use Lisp streams for output.
* System design:
- Setting a (DECLARE (SI::C-LOCAL)) inside a function, we advise the
compiler to make it local to an object file and do not export it
for general use outside this file, neither as C code nor in Lisp.
- New function cl_defvar() implements DEFVAR.
- Global variable si::*cblock* keeps a pointer to the descriptor of the
library being loaded (on systems which support DLLs).
* Visible changes:
- The C counterparts of the Lisp functions have now the prefix
cl_*. For instance, LIST-LENGTH is named cl_list_length(). There
are two types of functions. Those who take a fixed number of
arguments, are just called using C calling conventions:
cl_object form = c_string_to_object("(1 2 3 4)");
cl_object l = cl_list_length(form);
But there are functions which take a variable number of arguments:
in this case, the first argument must be the total number of
arguments. For instance
cl_object form = cl_read(0);
or
cl_object form = cl_read(1, Cnil);
- Renamed functions MF() and MM() to cl_def_c_function(),
cl_def_c_function_va() and cl_def_c_macro_va(). Removed
make_function() and make_si_function(), which had a more limited
purpose. The *_va() functions take as argument a C function with
prototype
cl_object (*function)(int narg, ...)
which means that the function should accept any number of
arguments and signal an error when the number is incorrect. The
functions without *_va() suffix, take as argument a C function
with prototype
cl_object (*function)()
and an integer "narg" denoting the number of arguments that this
function actually receives.
- Within the debugger, users are now able to evaluate expressions using the
lexical environment of the functions being debugged. Sample session:
> (defun foo (x) (cos x))
FOO
> (foo 'a)
A is not of type NUMBER.
Broken at COS.
>> :b
Backtrace: COS > foo > eval
>> :p
Broken at FOO.
>> :v
Block names: FOO.
Local variables:
X: A
>> (return-from foo (cos 2.0))
-0.4161468
- DISASSEMBLE can now either disassemble the bytecodes of an interpreted
function, or translate a lisp expression into C and show the result.
- New program "ecl-config" outputs either the flags compile ("ecl-config -c")
or to link ("ecl-config -l") a program using the ECL library.
- In compiled code, constants which are EQUALP are merged; that is, they
become EQ at run time.
- cl_special_form_p() renamed to cl_special_operator_p().
* ANSI compatibility:
- DEFINE-SYMBOL-MACRO finally implemented.
TODO:
=====
......
......@@ -76,6 +76,7 @@ BUILD-STAMP: config.status
install: BUILD-STAMP
$(INSTALL) -d $(PREFIX)$(bindir) $(PREFIX)$(mandir) $(PREFIX)$(libdir)/h
$(INSTALL_PROGRAM) -s $(TARGETS) $(PREFIX)$(bindir)
$(INSTALL_PROGRAM) ecl-config $(PREFIX)$(bindir)
$(INSTALL_DATA) $(srcdir)/etc/ecl.1 $(PREFIX)$(mandir)
$(INSTALL_DATA) BUILD-STAMP $(LSP_LIBRARIES) $(LIBRARIES) $(PREFIX)$(libdir)
$(INSTALL_DATA) h/config.h $(PREFIX)$(libdir)/h
......@@ -90,7 +91,7 @@ installgc:
uninstall:
rm -rf $(mandir)/ecl.1
rm -rf $(bindir)/ecl$(EXE)
for i in $(TARGETS) ecl-config; do rm -rf $(bindir)/$$i; done
rm -rf $(libdir)
cd doc; $(MAKE) uninstall
......
......@@ -109,7 +109,7 @@ configure___software_version=SOFTWARE_VERSION
CPP=`eval "echo $CPP"`
eval `${CPP} -D${host} ${tempcname} \
| grep 'configure___' \
| sed -e 's/^configure___\([^=]*=\)[ ]*\(.*[^ ]\) */\1"\2"/'`
| sed -e 's/^configure___\([^=]*\)=[ ]*\(.*[^ ]\) */\1="$\1 \2"/'`
rm ${tempcname}
]
AC_MSG_CHECKING(for ld flags when building shared libraries)
......
......@@ -18,6 +18,10 @@
(setf (symbol-function 'setf-gethash)
(symbol-function 'sb-impl::%puthash)) t
#+ecl
(setf (symbol-function 'setf-gethash)
(symbol-function 'si::hash-set))
(check-for-bug :hashlong-legacy-21
(defun symbole ()
(let ((b 0.)
......
......@@ -28,7 +28,7 @@ libdir = @libdir@
HDIR = $(top_srcdir)/h
HFILES = ../h/config.h $(HDIR)/ecl.h $(HDIR)/ecl-cmp.h\
$(HDIR)/machines.h $(HDIR)/object.h $(HDIR)/cs.h $(HDIR)/stacks.h\
$(HDIR)/external.h $(HDIR)/lisp_external.h $(HDIR)/eval.h\
$(HDIR)/external.h $(HDIR)/eval.h\
$(HDIR)/number.h $(HDIR)/page.h $(HDIR)/unify.h\
$(HDIR)/lwp.h $(HDIR)/critical.h
OBJS = main.o symbol.o package.o list.o\
......@@ -71,8 +71,8 @@ $(DPP): $(srcdir)/dpp.c symbols_list2.h
$(TRUE_CC) @CFLAGS@ -I../h -I./ -I$(HDIR) $(DEFS) $(srcdir)/dpp.c -o $@
symbols_list2.h: $(srcdir)/symbols_list.h Makefile
cat $(srcdir)/symbols_list.h | \
sed -e 's%{"\(.*\)",.*,.*,[ ]*NULL}%{"\1",NULL}%g' \
-e 's%{"\(.*\)",.*,.*,[ ]*\(.*\)}%{"\1","\2"}%g' \
sed -e 's%{"\(.*\)",.*,[ ]*NULL,.*}%{"\1",NULL}%g' \
-e 's%{"\(.*\)",.*,[ ]*\(.*\),.*}%{"\1","\2"}%g' \
-e 's%{NULL.*%{NULL,NULL}};%' > $@
#
......@@ -88,8 +88,5 @@ apply.o: apply.c $(HFILES) $(HDIR)/cs.h
#
# These files are interrelated
#
all_symbols.o: all_symbols.c symbols_def.h
all_symbols.o: all_symbols.c
$(CC) $(CFLAGS) -I./ all_symbols.c -o $@
symbols_def.h: $(srcdir)/symbols_list.h Makefile
cat $(srcdir)/symbols_list.h | grep '[ ]&' | \
sed 's/^.* &\([a-zA-Z_0-9]*\),.*/cl_object \1;/g' > symbols_def.h
......@@ -10,7 +10,6 @@
#define KEYWORD 10
#define FORM_ORDINARY 16
#include "symbols_def.h"
#include "symbols_list.h"
cl_index cl_num_symbols_in_core = 0;
......@@ -21,6 +20,7 @@ cl_index cl_num_symbols_in_core = 0;
cl_object output;
cl_object package;
cl_object found = Cnil;
cl_object maxarg = MAKE_FIXNUM(-1);
bool is_symbol;
@
assert_type_symbol(symbol);
......@@ -38,7 +38,7 @@ cl_index cl_num_symbols_in_core = 0;
output = @format(3, Cnil,
make_constant_string("((cl_object)(cl_symbols+~A))"),
MAKE_FIXNUM(p));
@(return found output)
@(return found output maxarg)
}
} else {
cl_object fun;
......@@ -50,6 +50,7 @@ cl_index cl_num_symbols_in_core = 0;
if (fun == SYM_FUN(s)) {
symbol = s;
found = Ct;
maxarg = MAKE_FIXNUM(fun->cfun.narg);
break;
}
}
......@@ -71,7 +72,7 @@ cl_index cl_num_symbols_in_core = 0;
l-= 2;
source++;
} else if (!is_symbol) {
c = 'L';
c = '_';
} else if (package == keyword_package) {
c = 'K';
} else {
......@@ -112,7 +113,7 @@ cl_index cl_num_symbols_in_core = 0;
} else if (c == ':') {
c = 'X';
} else {
@(return Cnil Cnil)
@(return Cnil Cnil maxarg)
}
*(dest++) = c;
output->string.fillp++;
......@@ -122,12 +123,12 @@ cl_index cl_num_symbols_in_core = 0;
*(dest++) = '\0';
if (!Null(package))
output = @si::string-concatenate(2,package,output);
@(return found output)
@(return found output maxarg)
@)
static void
make_this_symbol(int i, cl_object s, int code, const char *name, cl_object *loc,
cl_objectfn fun)
make_this_symbol(int i, cl_object s, int code, const char *name,
cl_objectfn fun, int narg)
{
enum stype stp;
cl_object package;
......@@ -157,24 +158,25 @@ make_this_symbol(int i, cl_object s, int code, const char *name, cl_object *loc,
sethash(s->symbol.name, package->pack.external, s);
SYM_VAL(s) = s;
} else {
cl_import(s, package);
cl_export(s, package);
cl_import2(s, package);
cl_export2(s, package);
}
if (loc != NULL)
*loc = s;
if (code == FORM_ORDINARY)
s->symbol.isform = TRUE;
else if (fun != NULL)
SYM_FUN(s) = make_cfun(fun, s, NULL);
else if (fun != NULL) {
cl_object f = cl_make_cfun_va(fun, s, NULL);
SYM_FUN(s) = f;
f->cfun.narg = narg;
}
cl_num_symbols_in_core = i + 1;
}
void
init_all_symbols(void)
{
int i, code;
int i, code, narg;
const char *name;
cl_object s, *loc;
cl_object s;
cl_objectfn fun;
/* We skip NIL and T */
......@@ -182,8 +184,8 @@ init_all_symbols(void)
s = (cl_object)(cl_symbols + i);
code = cl_symbols[i].init.type;
name = cl_symbols[i].init.name;
loc = cl_symbols[i].init.loc;
fun = (cl_objectfn)cl_symbols[i].init.fun;
make_this_symbol(i, s, code, name, loc, fun);
narg = cl_symbols[i].init.narg;
make_this_symbol(i, s, code, name, fun, narg);
}
}
......@@ -719,7 +719,7 @@ static int
t_from_type(cl_object type)
{ int t;
type = coerce_to_string(type);
type = cl_string(type);
for (t = (int)t_start ; t < (int)t_end ; t++) {
struct typemanager *tm = &tm_table[t];
if (tm->tm_name &&
......
......@@ -14,6 +14,8 @@
#include "ecl.h"
#include "page.h"
#include "gc.h"
#include "private/gc_priv.h"
#ifdef GBC_BOEHM
......@@ -45,8 +47,14 @@ cl_alloc_object(cl_type t)
}
tm = tm_of(t);
start_critical_section();
start_critical_section();
#if 0
obj = (cl_object)GC_malloc(tm->tm_size);
#else
obj = (cl_object)GC_malloc_explicitly_typed
(tm->tm_size & ~GC_DS_BITMAP,
tm->tm_size);
#endif
obj->d.t = t;
/* GC_malloc already resets objects */
end_critical_section();
......@@ -157,13 +165,18 @@ init_tm(cl_type t, char *name, cl_index elsize)
static int alloc_initialized = FALSE;
static void (*old_GC_push_other_roots)();
void
init_alloc(void)
{
static void stacks_scanner();
if (alloc_initialized) return;
alloc_initialized = TRUE;
GC_no_dls = 1;
GC_init_explicit_typing();
init_tm(t_shortfloat, "SHORT-FLOAT", /* 8 */
sizeof(struct shortfloat_struct));
......@@ -198,6 +211,34 @@ init_alloc(void)
init_tm(t_cont, "CONT", sizeof(struct cont));
init_tm(t_thread, "THREAD", sizeof(struct thread));
#endif /* THREADS */
old_GC_push_other_roots = GC_push_other_roots;
GC_push_other_roots = stacks_scanner;
}
/**********************************************************
* GARBAGE COLLECTOR *
**********************************************************/
static void
stacks_scanner(void)
{
if (cl_stack) {
GC_push_conditional(cl_stack, cl_stack_top,1);
GC_set_mark_bit(cl_stack);
}
if (frs_top && (frs_top >= frs_org)) {
GC_push_conditional(frs_org, frs_top+1,1);
GC_set_mark_bit(frs_org);
}
if (bds_top && (bds_top >= bds_org)) {
GC_push_conditional(bds_org, bds_top+1,1);
GC_set_mark_bit(bds_top);
}
if (NValues)
GC_push_all(Values, Values+NValues+1);
if (old_GC_push_other_roots)
(*old_GC_push_other_roots)();
}
/**********************************************************
......
This diff is collapsed.
......@@ -41,19 +41,19 @@ object_to_index(cl_object n)
}
}
@(defun row-major-aref (x indx)
cl_index j;
@
j = fixnnint(indx);
@(return aref(x, j))
@)
cl_object
cl_row_major_aref(cl_object x, cl_object indx)
{
cl_index j = fixnnint(indx);
@(return aref(x, j))
}
@(defun si::row-major-aset (x indx val)
cl_index j;
@
j = fixnnint(indx);
@(return aset(x, j, val))
@)
cl_object
si_row_major_aset(cl_object x, cl_object indx, cl_object val)
{
cl_index j = fixnnint(indx);
@(return aset(x, j, val))
}
@(defun aref (x &rest indx)
cl_index r, s, i, j;
......@@ -307,11 +307,14 @@ aset1(cl_object v, cl_index index, cl_object val)
(si:make-vector element-type dimension adjustable fill-pointer
displaced-to displaced-index-offset)
*/
@(defun si::make_vector (etype dim adj fillp displ disploff)
cl_object
si_make_vector(cl_object etype, cl_object dim, cl_object adj,
cl_object fillp, cl_object displ, cl_object disploff)
{
cl_index d, f;
cl_object x;
cl_elttype aet;
@
aet = get_elttype(etype);
if ((d = fixnnint(dim)) > ADIMLIM)
FEerror("The vector dimension, ~D, is too large.", 1, dim);
......@@ -346,7 +349,7 @@ aset1(cl_object v, cl_index index, cl_object val)
else
displace(x, displ, disploff);
@(return x)
@)
}
void
array_allocself(cl_object x)
......@@ -477,9 +480,11 @@ array_address(cl_object x, cl_index inc)
}
}
@(defun array_element_type (a)
cl_object
cl_array_element_type(cl_object a)
{
cl_object output;
@
switch (array_elttype(a)) {
case aet_object: output = Ct; break;
case aet_ch: output = @'base-char'; break;
......@@ -491,7 +496,7 @@ array_address(cl_object x, cl_index inc)
case aet_i8: output = @'integer8'; break;
}
@(return output)
@)
}
/*
Displace(from, to, offset) displaces the from-array
......@@ -598,16 +603,19 @@ array_elttype(cl_object x)
}
}
@(defun array_rank (a)
@
cl_object
cl_array_rank(cl_object a)
{
assert_type_array(a);
@(return ((type_of(a) == t_array) ? MAKE_FIXNUM(a->array.rank)
: MAKE_FIXNUM(1)))
@)
}
@(defun array_dimension (a index)
cl_object
cl_array_dimension(cl_object a, cl_object index)
{
cl_index i, dim;
@
i = fixnnint(index);
switch (type_of(a)) {
case t_array:
......@@ -631,32 +639,37 @@ ILLEGAL: FEerror("~S is an illegal axis-number to the array ~S.",
FEwrong_type_argument(@'array', a);
}
@(return MAKE_FIXNUM(dim))
@)
}
@(defun array_total_size (a)
@
cl_object
cl_array_total_size(cl_object a)
{
assert_type_array(a);
@(return MAKE_FIXNUM(a->array.dim))
@)
}
@(defun adjustable_array_p (a)
@
cl_object
cl_adjustable_array_p(cl_object a)
{
assert_type_array(a);
@(return (a->array.adjustable ? Ct : Cnil))
@)
}
/*
Internal function for checking if an array is displaced.
*/
@(defun si::displaced_array_p (a)
@
cl_object
si_displaced_array_p(cl_object a)
{
assert_type_array(a);
@(return ((CAR(a->array.displaced) != Cnil) ? Ct : Cnil))
@)
}
@(defun svref (x index)
cl_object
cl_svref(cl_object x, cl_object index)
{
cl_index i;
@
if (type_of(x) != t_vector ||
x->vector.adjustable ||
x->vector.hasfillp ||
......@@ -666,11 +679,13 @@ ILLEGAL: FEerror("~S is an illegal axis-number to the array ~S.",
if ((i = fixnnint(index)) >= x->vector.dim)
illegal_index(x, index);
@(return x->vector.self.t[i])
@)
}
@(defun si::svset (x index v)
cl_object
si_svset(cl_object x, cl_object index, cl_object v)
{
cl_index i;
@
if (type_of(x) != t_vector ||
x->vector.adjustable ||
x->vector.hasfillp ||
......@@ -680,11 +695,13 @@ ILLEGAL: FEerror("~S is an illegal axis-number to the array ~S.",
if ((i = fixnnint(index)) >= x->vector.dim)
illegal_index(x, index);
@(return (x->vector.self.t[i] = v))
@)
}
@(defun array_has_fill_pointer_p (a)
cl_object
cl_array_has_fill_pointer_p(cl_object a)
{
cl_object r;
@
switch (type_of(a)) {
case t_array:
r = Cnil; break;
......@@ -697,22 +714,25 @@ ILLEGAL: FEerror("~S is an illegal axis-number to the array ~S.",
FEwrong_type_argument(@'array', a);
}
@(return r)
@)
}
@(defun fill_pointer (a)
@
cl_object
cl_fill_pointer(cl_object a)
{
assert_type_vector(a);
if (a->vector.hasfillp)
@(return MAKE_FIXNUM(a->vector.fillp))