1 /* T I N Y S C H E M E 1 . 3 5
2 * Dimitrios Souflis (dsouflis@acm.org)
3 * Based on MiniScheme (original credits follow)
4 * (MINISCM) coded by Atsushi Moriwaki (11/5/1989)
5 * (MINISCM) E-MAIL : moriwaki@kurims.kurims.kyoto-u.ac.jp
6 * (MINISCM) This version has been modified by R.C. Secrist.
8 * (MINISCM) Mini-Scheme is now maintained by Akira KIDA.
10 * (MINISCM) This is a revised and modified version by Akira KIDA.
11 * (MINISCM) current version is 0.85k4 (15 May 1994)
16 \brief The TinyScheme compiler
24 #define _SCHEME_SOURCE
25 #include "scheme-private.h"
39 #include <unistd.h> /* access() on Linux */
44 #define stricmp strcasecmp
47 /* Used for documentation purposes, to signal functions in 'interface' */
62 #define TOK_SHARP_CONST 11
65 # define BACKQUOTE '`'
68 * Basic memory allocation units
71 #define banner "TinyScheme 1.35"
82 static int stricmp(const char *s1
, const char *s2
)
96 #endif /* macintosh */
99 static const char *strlwr(char *s
) {
102 *s
=tolower((int) *s
);
114 # define InitFile "init.scm"
117 #ifndef FIRST_CELLSEGS
118 # define FIRST_CELLSEGS 3
136 T_LAST_SYSTEM_TYPE
=14
139 /* ADJ is enough slack to align cells in a TYPE_BITS-bit boundary */
142 #define T_MASKTYPE 31 /* 0000000000011111 */
143 #define T_SYNTAX 4096 /* 0001000000000000 */
144 #define T_IMMUTABLE 8192 /* 0010000000000000 */
145 #define T_ATOM 16384 /* 0100000000000000 */ /* only for gc */
146 #define CLRATOM 49151 /* 1011111111111111 */ /* only for gc */
147 #define MARK 32768 /* 1000000000000000 */
148 #define UNMARK 32767 /* 0111111111111111 */
151 static num
num_add(num a
, num b
);
152 static num
num_mul(num a
, num b
);
153 static num
num_div(num a
, num b
);
154 static num
num_intdiv(num a
, num b
);
155 static num
num_sub(num a
, num b
);
156 static num
num_rem(num a
, num b
);
157 static num
num_mod(num a
, num b
);
158 static int num_eq(num a
, num b
);
159 static int num_gt(num a
, num b
);
160 static int num_ge(num a
, num b
);
161 static int num_lt(num a
, num b
);
162 static int num_le(num a
, num b
);
165 static double round_per_R5RS(double x
);
167 static int is_zero_double(double x
);
172 /* macros for cell operations */
173 #define typeflag(p) ((p)->_flag)
174 #define type(p) (typeflag(p)&T_MASKTYPE)
176 INTERFACE INLINE
int is_string(pointer p
) { return (type(p
)==T_STRING
); }
177 #define strvalue(p) ((p)->_object._string._svalue)
178 #define strlength(p) ((p)->_object._string._length)
180 INTERFACE INLINE
int is_vector(pointer p
) { return (type(p
)==T_VECTOR
); }
181 INTERFACE
static void fill_vector(pointer vec
, pointer obj
);
182 INTERFACE
static pointer
vector_elem(pointer vec
, int ielem
);
183 INTERFACE
static pointer
set_vector_elem(pointer vec
, int ielem
, pointer a
);
184 INTERFACE INLINE
int is_number(pointer p
) { return (type(p
)==T_NUMBER
); }
185 INTERFACE INLINE
int is_integer(pointer p
) {
186 return ((p
)->_object
._number
.is_fixnum
);
188 INTERFACE INLINE
int is_real(pointer p
) {
189 return (!(p
)->_object
._number
.is_fixnum
);
192 INTERFACE INLINE
int is_character(pointer p
) { return (type(p
)==T_CHARACTER
); }
193 INTERFACE INLINE
char *string_value(pointer p
) { return strvalue(p
); }
194 INLINE num
nvalue(pointer p
) { return ((p
)->_object
._number
); }
195 INTERFACE
long ivalue(pointer p
) { return (is_integer(p
)?(p
)->_object
._number
.value
.ivalue
:(long)(p
)->_object
._number
.value
.rvalue
); }
196 INTERFACE
double rvalue(pointer p
) { return (!is_integer(p
)?(p
)->_object
._number
.value
.rvalue
:(double)(p
)->_object
._number
.value
.ivalue
); }
197 #define ivalue_unchecked(p) ((p)->_object._number.value.ivalue)
198 #define rvalue_unchecked(p) ((p)->_object._number.value.rvalue)
199 #define set_integer(p) (p)->_object._number.is_fixnum=1;
200 #define set_real(p) (p)->_object._number.is_fixnum=0;
201 INTERFACE
long charvalue(pointer p
) { return ivalue_unchecked(p
); }
203 INTERFACE INLINE
int is_port(pointer p
) { return (type(p
)==T_PORT
); }
204 #define is_inport(p) (type(p)==T_PORT && p->_object._port->kind&port_input)
205 #define is_outport(p) (type(p)==T_PORT && p->_object._port->kind&port_output)
207 INTERFACE INLINE
int is_pair(pointer p
) { return (type(p
)==T_PAIR
); }
208 #define car(p) ((p)->_object._cons._car)
209 #define cdr(p) ((p)->_object._cons._cdr)
210 INTERFACE pointer
pair_car(pointer p
) { return car(p
); }
211 INTERFACE pointer
pair_cdr(pointer p
) { return cdr(p
); }
212 INTERFACE pointer
set_car(pointer p
, pointer q
) { return car(p
)=q
; }
213 INTERFACE pointer
set_cdr(pointer p
, pointer q
) { return cdr(p
)=q
; }
215 INTERFACE INLINE
int is_symbol(pointer p
) { return (type(p
)==T_SYMBOL
); }
216 INTERFACE INLINE
char *symname(pointer p
) { return strvalue(car(p
)); }
218 SCHEME_EXPORT INLINE
int hasprop(pointer p
) { return (typeflag(p
)&T_SYMBOL
); }
219 #define symprop(p) cdr(p)
222 INTERFACE INLINE
int is_syntax(pointer p
) { return (typeflag(p
)&T_SYNTAX
); }
223 INTERFACE INLINE
int is_proc(pointer p
) { return (type(p
)==T_PROC
); }
224 INTERFACE INLINE
int is_foreign(pointer p
) { return (type(p
)==T_FOREIGN
); }
225 INTERFACE INLINE
char *syntaxname(pointer p
) { return strvalue(car(p
)); }
226 #define procnum(p) ivalue(p)
227 static const char *procname(pointer x
);
229 INTERFACE INLINE
int is_closure(pointer p
) { return (type(p
)==T_CLOSURE
); }
230 INTERFACE INLINE
int is_macro(pointer p
) { return (type(p
)==T_MACRO
); }
231 INTERFACE INLINE pointer
closure_code(pointer p
) { return car(p
); }
232 INTERFACE INLINE pointer
closure_env(pointer p
) { return cdr(p
); }
234 INTERFACE INLINE
int is_continuation(pointer p
) { return (type(p
)==T_CONTINUATION
); }
235 #define cont_dump(p) cdr(p)
237 /* To do: promise should be forced ONCE only */
238 INTERFACE INLINE
int is_promise(pointer p
) { return (type(p
)==T_PROMISE
); }
240 INTERFACE INLINE
int is_environment(pointer p
) { return (type(p
)==T_ENVIRONMENT
); }
241 #define setenvironment(p) typeflag(p) = T_ENVIRONMENT
243 #define is_atom(p) (typeflag(p)&T_ATOM)
244 #define setatom(p) typeflag(p) |= T_ATOM
245 #define clratom(p) typeflag(p) &= CLRATOM
247 #define is_mark(p) (typeflag(p)&MARK)
248 #define setmark(p) typeflag(p) |= MARK
249 #define clrmark(p) typeflag(p) &= UNMARK
251 INTERFACE INLINE
int is_immutable(pointer p
) { return (typeflag(p
)&T_IMMUTABLE
); }
252 /*#define setimmutable(p) typeflag(p) |= T_IMMUTABLE*/
253 INTERFACE INLINE
void setimmutable(pointer p
) { typeflag(p
) |= T_IMMUTABLE
; }
255 #define caar(p) car(car(p))
256 #define cadr(p) car(cdr(p))
257 #define cdar(p) cdr(car(p))
258 #define cddr(p) cdr(cdr(p))
259 #define cadar(p) car(cdr(car(p)))
260 #define caddr(p) car(cdr(cdr(p)))
261 #define cadaar(p) car(cdr(car(car(p))))
262 #define cadddr(p) car(cdr(cdr(cdr(p))))
263 #define cddddr(p) cdr(cdr(cdr(cdr(p))))
265 #if USE_CHAR_CLASSIFIERS
266 static INLINE
int Cisalpha(int c
) { return isascii(c
) && isalpha(c
); }
267 static INLINE
int Cisdigit(int c
) { return isascii(c
) && isdigit(c
); }
268 static INLINE
int Cisspace(int c
) { return isascii(c
) && isspace(c
); }
269 static INLINE
int Cisupper(int c
) { return isascii(c
) && isupper(c
); }
270 static INLINE
int Cislower(int c
) { return isascii(c
) && islower(c
); }
274 static const char *charnames
[32]={
309 static int is_ascii_name(const char *name
, int *pc
) {
311 for(i
=0; i
<32; i
++) {
312 if(stricmp(name
,charnames
[i
])==0) {
317 if(stricmp(name
,"del")==0) {
326 static int file_push(scheme
*sc
, const char *fname
);
327 static void file_pop(scheme
*sc
);
328 static int file_interactive(scheme
*sc
);
329 static INLINE
int is_one_of(char *s
, int c
);
330 static int alloc_cellseg(scheme
*sc
, int n
);
331 static long binary_decode(const char *s
);
332 static INLINE pointer
get_cell(scheme
*sc
, pointer a
, pointer b
);
333 static pointer
_get_cell(scheme
*sc
, pointer a
, pointer b
);
334 static pointer
get_consecutive_cells(scheme
*sc
, int n
);
335 static pointer
find_consecutive_cells(scheme
*sc
, int n
);
336 static void finalize_cell(scheme
*sc
, pointer a
);
337 static int count_consecutive_cells(pointer x
, int needed
);
338 static pointer
find_slot_in_env(scheme
*sc
, pointer env
, pointer sym
, int all
);
339 static pointer
mk_number(scheme
*sc
, num n
);
340 static pointer
mk_empty_string(scheme
*sc
, int len
, char fill
);
341 static char *store_string(scheme
*sc
, int len
, const char *str
, char fill
);
342 static pointer
mk_vector(scheme
*sc
, int len
);
343 static pointer
mk_atom(scheme
*sc
, char *q
);
344 static pointer
mk_sharp_const(scheme
*sc
, char *name
);
345 static pointer
mk_port(scheme
*sc
, port
*p
);
346 static pointer
port_from_filename(scheme
*sc
, const char *fn
, int prop
);
347 static pointer
port_from_file(scheme
*sc
, FILE *, int prop
);
348 static pointer
port_from_string(scheme
*sc
, char *start
, char *past_the_end
, int prop
);
349 static port
*port_rep_from_filename(scheme
*sc
, const char *fn
, int prop
);
350 static port
*port_rep_from_file(scheme
*sc
, FILE *, int prop
);
351 static port
*port_rep_from_string(scheme
*sc
, char *start
, char *past_the_end
, int prop
);
352 static void port_close(scheme
*sc
, pointer p
, int flag
);
353 static void mark(pointer a
);
354 static void gc(scheme
*sc
, pointer a
, pointer b
);
355 static int basic_inchar(port
*pt
);
356 static int inchar(scheme
*sc
);
357 static void backchar(scheme
*sc
, int c
);
358 static char *readstr_upto(scheme
*sc
, char *delim
);
359 static pointer
readstrexp(scheme
*sc
);
360 static INLINE
void skipspace(scheme
*sc
);
361 static int token(scheme
*sc
);
362 static void printslashstring(scheme
*sc
, char *s
, int len
);
363 static void atom2str(scheme
*sc
, pointer l
, int f
, char **pp
, int *plen
);
364 static void printatom(scheme
*sc
, pointer l
, int f
);
365 static pointer
mk_proc(scheme
*sc
, enum scheme_opcodes op
);
366 static pointer
mk_closure(scheme
*sc
, pointer c
, pointer e
);
367 static pointer
mk_continuation(scheme
*sc
, pointer d
);
368 static pointer
reverse(scheme
*sc
, pointer a
);
369 static pointer
reverse_in_place(scheme
*sc
, pointer term
, pointer list
);
370 static pointer
append(scheme
*sc
, pointer a
, pointer b
);
371 static int list_length(scheme
*sc
, pointer a
);
372 static int eqv(pointer a
, pointer b
);
373 static void dump_stack_mark(scheme
*);
374 static pointer
opexe_0(scheme
*sc
, enum scheme_opcodes op
);
375 static pointer
opexe_1(scheme
*sc
, enum scheme_opcodes op
);
376 static pointer
opexe_2(scheme
*sc
, enum scheme_opcodes op
);
377 static pointer
opexe_3(scheme
*sc
, enum scheme_opcodes op
);
378 static pointer
opexe_4(scheme
*sc
, enum scheme_opcodes op
);
379 static pointer
opexe_5(scheme
*sc
, enum scheme_opcodes op
);
380 static pointer
opexe_6(scheme
*sc
, enum scheme_opcodes op
);
381 static void Eval_Cycle(scheme
*sc
, enum scheme_opcodes op
);
382 static void assign_syntax(scheme
*sc
, char *name
);
383 static int syntaxnum(pointer p
);
384 static void assign_proc(scheme
*sc
, enum scheme_opcodes
, char *name
);
386 #define num_ivalue(n) (n.is_fixnum?(n).value.ivalue:(long)(n).value.rvalue)
387 #define num_rvalue(n) (!n.is_fixnum?(n).value.rvalue:(double)(n).value.ivalue)
389 static num
num_add(num a
, num b
) {
391 ret
.is_fixnum
=a
.is_fixnum
&& b
.is_fixnum
;
393 ret
.value
.ivalue
= a
.value
.ivalue
+b
.value
.ivalue
;
395 ret
.value
.rvalue
=num_rvalue(a
)+num_rvalue(b
);
400 static num
num_mul(num a
, num b
) {
402 ret
.is_fixnum
=a
.is_fixnum
&& b
.is_fixnum
;
404 ret
.value
.ivalue
= a
.value
.ivalue
*b
.value
.ivalue
;
406 ret
.value
.rvalue
=num_rvalue(a
)*num_rvalue(b
);
411 static num
num_div(num a
, num b
) {
413 ret
.is_fixnum
=a
.is_fixnum
&& b
.is_fixnum
&& a
.value
.ivalue
%b
.value
.ivalue
==0;
415 ret
.value
.ivalue
= a
.value
.ivalue
/b
.value
.ivalue
;
417 ret
.value
.rvalue
=num_rvalue(a
)/num_rvalue(b
);
422 static num
num_intdiv(num a
, num b
) {
424 ret
.is_fixnum
=a
.is_fixnum
&& b
.is_fixnum
;
426 ret
.value
.ivalue
= a
.value
.ivalue
/b
.value
.ivalue
;
428 ret
.value
.rvalue
=num_rvalue(a
)/num_rvalue(b
);
433 static num
num_sub(num a
, num b
) {
435 ret
.is_fixnum
=a
.is_fixnum
&& b
.is_fixnum
;
437 ret
.value
.ivalue
= a
.value
.ivalue
-b
.value
.ivalue
;
439 ret
.value
.rvalue
=num_rvalue(a
)-num_rvalue(b
);
444 static num
num_rem(num a
, num b
) {
447 ret
.is_fixnum
=a
.is_fixnum
&& b
.is_fixnum
;
451 /* modulo should have same sign as second operand */
456 } else if (res
< 0) {
461 ret
.value
.ivalue
=res
;
465 static num
num_mod(num a
, num b
) {
468 ret
.is_fixnum
=a
.is_fixnum
&& b
.is_fixnum
;
472 if(res
*e2
<0) { /* modulo should have same sign as second operand */
480 ret
.value
.ivalue
=res
;
484 static int num_eq(num a
, num b
) {
486 int is_fixnum
=a
.is_fixnum
&& b
.is_fixnum
;
488 ret
= a
.value
.ivalue
==b
.value
.ivalue
;
490 ret
=num_rvalue(a
)==num_rvalue(b
);
496 static int num_gt(num a
, num b
) {
498 int is_fixnum
=a
.is_fixnum
&& b
.is_fixnum
;
500 ret
= a
.value
.ivalue
>b
.value
.ivalue
;
502 ret
=num_rvalue(a
)>num_rvalue(b
);
507 static int num_ge(num a
, num b
) {
511 static int num_lt(num a
, num b
) {
513 int is_fixnum
=a
.is_fixnum
&& b
.is_fixnum
;
515 ret
= a
.value
.ivalue
<b
.value
.ivalue
;
517 ret
=num_rvalue(a
)<num_rvalue(b
);
522 static int num_le(num a
, num b
) {
527 /* Round to nearest. Round to even if midway */
528 static double round_per_R5RS(double x
) {
538 if(fmod(fl
,2.0)==0.0) { /* I imagine this holds */
547 static int is_zero_double(double x
) {
548 return x
<DBL_MIN
&& x
>-DBL_MIN
;
551 static long binary_decode(const char *s
) {
554 while(*s
!=0 && (*s
=='1' || *s
=='0')) {
563 /* allocate new cell segment */
564 static int alloc_cellseg(scheme
*sc
, int n
) {
573 if(adj
<sizeof(struct cell
)) {
574 adj
=sizeof(struct cell
);
577 for (k
= 0; k
< n
; k
++) {
578 if (sc
->last_cell_seg
>= CELL_NSEGMENT
- 1)
580 cp
= (char*) sc
->malloc(CELL_SEGSIZE
* sizeof(struct cell
)+adj
);
583 i
= ++sc
->last_cell_seg
;
584 sc
->alloc_seg
[i
] = cp
;
585 /* adjust in TYPE_BITS-bit boundary */
586 if((unsigned long)cp
%adj
!=0) {
587 cp
=(char*)(adj
*((unsigned long)cp
/adj
+1));
589 /* insert new segment in address order */
591 sc
->cell_seg
[i
] = newp
;
592 while (i
> 0 && sc
->cell_seg
[i
- 1] > sc
->cell_seg
[i
]) {
594 sc
->cell_seg
[i
] = sc
->cell_seg
[i
- 1];
595 sc
->cell_seg
[--i
] = p
;
597 sc
->fcells
+= CELL_SEGSIZE
;
598 last
= newp
+ CELL_SEGSIZE
- 1;
599 for (p
= newp
; p
<= last
; p
++) {
604 /* insert new cells in address order on free list */
605 if (sc
->free_cell
== sc
->NIL
|| p
< sc
->free_cell
) {
606 cdr(last
) = sc
->free_cell
;
607 sc
->free_cell
= newp
;
610 while (cdr(p
) != sc
->NIL
&& newp
> cdr(p
))
619 static INLINE pointer
get_cell(scheme
*sc
, pointer a
, pointer b
) {
620 if (sc
->free_cell
!= sc
->NIL
) {
621 pointer x
= sc
->free_cell
;
622 sc
->free_cell
= cdr(x
);
626 return _get_cell (sc
, a
, b
);
630 /* get new cell. parameter a, b is marked by gc. */
631 static pointer
_get_cell(scheme
*sc
, pointer a
, pointer b
) {
638 if (sc
->free_cell
== sc
->NIL
) {
640 if (sc
->fcells
< sc
->last_cell_seg
*8
641 || sc
->free_cell
== sc
->NIL
) {
642 /* if only a few recovered, get more to avoid fruitless gc's */
643 if (!alloc_cellseg(sc
,1) && sc
->free_cell
== sc
->NIL
) {
650 sc
->free_cell
= cdr(x
);
655 static pointer
get_consecutive_cells(scheme
*sc
, int n
) {
662 /* Are there any cells available? */
663 x
=find_consecutive_cells(sc
,n
);
665 /* If not, try gc'ing some */
666 gc(sc
, sc
->NIL
, sc
->NIL
);
667 x
=find_consecutive_cells(sc
,n
);
669 /* If there still aren't, try getting more heap */
670 if (!alloc_cellseg(sc
,1)) {
675 x
=find_consecutive_cells(sc
,n
);
677 /* If all fail, report failure */
685 static int count_consecutive_cells(pointer x
, int needed
) {
690 if(n
>needed
) return n
;
695 static pointer
find_consecutive_cells(scheme
*sc
, int n
) {
700 while(*pp
!=sc
->NIL
) {
701 cnt
=count_consecutive_cells(*pp
,n
);
713 /* get new cons cell */
714 pointer
_cons(scheme
*sc
, pointer a
, pointer b
, int immutable
) {
715 pointer x
= get_cell(sc
,a
, b
);
717 typeflag(x
) = T_PAIR
;
726 /* ========== oblist implementation ========== */
728 #ifndef USE_OBJECT_LIST
730 static int hash_fn(const char *key
, int table_size
);
732 static pointer
oblist_initial_value(scheme
*sc
)
734 return mk_vector(sc
, 461); /* probably should be bigger */
737 /* returns the new symbol */
738 static pointer
oblist_add_by_name(scheme
*sc
, const char *name
)
743 x
= immutable_cons(sc
, mk_string(sc
, name
), sc
->NIL
);
744 typeflag(x
) = T_SYMBOL
;
745 setimmutable(car(x
));
747 location
= hash_fn(name
, ivalue_unchecked(sc
->oblist
));
748 set_vector_elem(sc
->oblist
, location
,
749 immutable_cons(sc
, x
, vector_elem(sc
->oblist
, location
)));
753 static INLINE pointer
oblist_find_by_name(scheme
*sc
, const char *name
)
759 location
= hash_fn(name
, ivalue_unchecked(sc
->oblist
));
760 for (x
= vector_elem(sc
->oblist
, location
); x
!= sc
->NIL
; x
= cdr(x
)) {
762 /* case-insensitive, per R5RS section 2. */
763 if(stricmp(name
, s
) == 0) {
770 static pointer
oblist_all_symbols(scheme
*sc
)
774 pointer ob_list
= sc
->NIL
;
776 for (i
= 0; i
< ivalue_unchecked(sc
->oblist
); i
++) {
777 for (x
= vector_elem(sc
->oblist
, i
); x
!= sc
->NIL
; x
= cdr(x
)) {
778 ob_list
= cons(sc
, x
, ob_list
);
786 static pointer
oblist_initial_value(scheme
*sc
)
791 static INLINE pointer
oblist_find_by_name(scheme
*sc
, const char *name
)
796 for (x
= sc
->oblist
; x
!= sc
->NIL
; x
= cdr(x
)) {
798 /* case-insensitive, per R5RS section 2. */
799 if(stricmp(name
, s
) == 0) {
806 /* returns the new symbol */
807 static pointer
oblist_add_by_name(scheme
*sc
, const char *name
)
811 x
= immutable_cons(sc
, mk_string(sc
, name
), sc
->NIL
);
812 typeflag(x
) = T_SYMBOL
;
813 setimmutable(car(x
));
814 sc
->oblist
= immutable_cons(sc
, x
, sc
->oblist
);
817 static pointer
oblist_all_symbols(scheme
*sc
)
824 static pointer
mk_port(scheme
*sc
, port
*p
) {
825 pointer x
= get_cell(sc
, sc
->NIL
, sc
->NIL
);
827 typeflag(x
) = T_PORT
|T_ATOM
;
832 pointer
mk_foreign_func(scheme
*sc
, foreign_func f
) {
833 pointer x
= get_cell(sc
, sc
->NIL
, sc
->NIL
);
835 typeflag(x
) = (T_FOREIGN
| T_ATOM
);
840 INTERFACE pointer
mk_character(scheme
*sc
, int c
) {
841 pointer x
= get_cell(sc
,sc
->NIL
, sc
->NIL
);
843 typeflag(x
) = (T_CHARACTER
| T_ATOM
);
844 ivalue_unchecked(x
)= c
;
849 /* get number atom (integer) */
850 INTERFACE pointer
mk_integer(scheme
*sc
, long num
) {
851 pointer x
= get_cell(sc
,sc
->NIL
, sc
->NIL
);
853 typeflag(x
) = (T_NUMBER
| T_ATOM
);
854 ivalue_unchecked(x
)= num
;
859 INTERFACE pointer
mk_real(scheme
*sc
, double n
) {
860 pointer x
= get_cell(sc
,sc
->NIL
, sc
->NIL
);
862 typeflag(x
) = (T_NUMBER
| T_ATOM
);
863 rvalue_unchecked(x
)= n
;
868 static pointer
mk_number(scheme
*sc
, num n
) {
870 return mk_integer(sc
,n
.value
.ivalue
);
872 return mk_real(sc
,n
.value
.rvalue
);
876 /* allocate name to string area */
877 static char *store_string(scheme
*sc
, int len_str
, const char *str
, char fill
) {
880 q
=(char*)sc
->malloc(len_str
+1);
888 memset(q
, fill
, len_str
);
895 INTERFACE pointer
mk_string(scheme
*sc
, const char *str
) {
896 return mk_counted_string(sc
,str
,strlen(str
));
899 INTERFACE pointer
mk_counted_string(scheme
*sc
, const char *str
, int len
) {
900 pointer x
= get_cell(sc
, sc
->NIL
, sc
->NIL
);
902 strvalue(x
) = store_string(sc
,len
,str
,0);
903 typeflag(x
) = (T_STRING
| T_ATOM
);
908 static pointer
mk_empty_string(scheme
*sc
, int len
, char fill
) {
909 pointer x
= get_cell(sc
, sc
->NIL
, sc
->NIL
);
911 strvalue(x
) = store_string(sc
,len
,0,fill
);
912 typeflag(x
) = (T_STRING
| T_ATOM
);
917 INTERFACE
static pointer
mk_vector(scheme
*sc
, int len
) {
918 pointer x
=get_consecutive_cells(sc
,len
/2+len
%2+1);
919 typeflag(x
) = (T_VECTOR
| T_ATOM
);
920 ivalue_unchecked(x
)=len
;
922 fill_vector(x
,sc
->NIL
);
926 INTERFACE
static void fill_vector(pointer vec
, pointer obj
) {
928 int num
=ivalue(vec
)/2+ivalue(vec
)%2;
929 for(i
=0; i
<num
; i
++) {
930 typeflag(vec
+1+i
) = T_PAIR
;
931 setimmutable(vec
+1+i
);
937 INTERFACE
static pointer
vector_elem(pointer vec
, int ielem
) {
946 INTERFACE
static pointer
set_vector_elem(pointer vec
, int ielem
, pointer a
) {
949 return car(vec
+1+n
)=a
;
951 return cdr(vec
+1+n
)=a
;
956 INTERFACE pointer
mk_symbol(scheme
*sc
, const char *name
) {
959 /* first check oblist */
960 x
= oblist_find_by_name(sc
, name
);
964 x
= oblist_add_by_name(sc
, name
);
969 INTERFACE pointer
gensym(scheme
*sc
) {
973 for(; sc
->gensym_cnt
<LONG_MAX
; sc
->gensym_cnt
++) {
974 sprintf(name
,"gensym-%ld",sc
->gensym_cnt
);
976 /* first check oblist */
977 x
= oblist_find_by_name(sc
, name
);
982 x
= oblist_add_by_name(sc
, name
);
990 /* make symbol or number atom from string */
991 static pointer
mk_atom(scheme
*sc
, char *q
) {
997 if((p
=strstr(q
,"::"))!=0) {
999 return cons(sc
, sc
->COLON_HOOK
,
1003 cons(sc
, mk_atom(sc
,p
+2), sc
->NIL
)),
1004 cons(sc
, mk_symbol(sc
,strlwr(q
)), sc
->NIL
)));
1010 if ((c
== '+') || (c
== '-')) {
1016 if (!isdigit((int) c
)) {
1017 return (mk_symbol(sc
, strlwr(q
)));
1019 } else if (c
== '.') {
1022 if (!isdigit((int) c
)) {
1023 return (mk_symbol(sc
, strlwr(q
)));
1025 } else if (!isdigit((int) c
)) {
1026 return (mk_symbol(sc
, strlwr(q
)));
1029 for ( ; (c
= *p
) != 0; ++p
) {
1030 if (!isdigit((int) c
)) {
1032 if(!has_dec_point
) {
1037 else if ((c
== 'e') || (c
== 'E')) {
1039 has_dec_point
= 1; /* decimal point illegal
1042 if ((*p
== '-') || (*p
== '+') || isdigit((int) *p
)) {
1047 return (mk_symbol(sc
, strlwr(q
)));
1051 return mk_real(sc
,atof(q
));
1053 return (mk_integer(sc
, atol(q
)));
1057 static pointer
mk_sharp_const(scheme
*sc
, char *name
) {
1061 if (!strcmp(name
, "t"))
1063 else if (!strcmp(name
, "f"))
1065 else if (*name
== 'o') {/* #o (octal) */
1066 sprintf(tmp
, "0%s", name
+1);
1067 sscanf(tmp
, "%lo", &x
);
1068 return (mk_integer(sc
, x
));
1069 } else if (*name
== 'd') { /* #d (decimal) */
1070 sscanf(name
+1, "%ld", &x
);
1071 return (mk_integer(sc
, x
));
1072 } else if (*name
== 'x') { /* #x (hex) */
1073 sprintf(tmp
, "0x%s", name
+1);
1074 sscanf(tmp
, "%lx", &x
);
1075 return (mk_integer(sc
, x
));
1076 } else if (*name
== 'b') { /* #b (binary) */
1077 x
= binary_decode(name
+1);
1078 return (mk_integer(sc
, x
));
1079 } else if (*name
== '\\') { /* #\w (character) */
1081 if(stricmp(name
+1,"space")==0) {
1083 } else if(stricmp(name
+1,"newline")==0) {
1085 } else if(stricmp(name
+1,"return")==0) {
1087 } else if(stricmp(name
+1,"tab")==0) {
1089 } else if(name
[1]=='x' && name
[2]!=0) {
1091 if(sscanf(name
+2,"%x",&c1
)==1 && c1
<256) {
1097 } else if(is_ascii_name(name
+1,&c
)) {
1100 } else if(name
[2]==0) {
1105 return mk_character(sc
,c
);
1110 /* ========== garbage collector ========== */
1113 * We use algorithm E (Knuth, The Art of Computer Programming Vol.1,
1114 * sec. 2.3.5), the Schorr-Deutsch-Waite link-inversion algorithm,
1117 static void mark(pointer a
) {
1125 int num
=ivalue_unchecked(p
)/2+ivalue_unchecked(p
)%2;
1126 for(i
=0; i
<num
; i
++) {
1127 /* Vector cells will be treated like ordinary cells */
1135 if (q
&& !is_mark(q
)) {
1136 setatom(p
); /* a note that we have moved car */
1142 E5
: q
= cdr(p
); /* down cdr */
1143 if (q
&& !is_mark(q
)) {
1149 E6
: /* up. Undo the link switching from steps E4 and E5. */
1167 /* garbage collection. parameter a, b is marked. */
1168 static void gc(scheme
*sc
, pointer a
, pointer b
) {
1172 if(sc
->gc_verbose
) {
1173 putstr(sc
, "gc...");
1176 /* mark system globals */
1178 mark(sc
->global_env
);
1180 /* mark current registers */
1184 dump_stack_mark(sc
);
1187 mark(sc
->save_inport
);
1191 /* mark variables a, b */
1195 /* garbage collect */
1198 sc
->free_cell
= sc
->NIL
;
1199 /* free-list is kept sorted by address so as to maintain consecutive
1200 ranges, if possible, for use with vectors. Here we scan the cells
1201 (which are also kept sorted by address) downwards to build the
1202 free-list in sorted order.
1204 for (i
= sc
->last_cell_seg
; i
>= 0; i
--) {
1205 p
= sc
->cell_seg
[i
] + CELL_SEGSIZE
;
1206 while (--p
>= sc
->cell_seg
[i
]) {
1211 if (typeflag(p
) != 0) {
1212 finalize_cell(sc
, p
);
1217 cdr(p
) = sc
->free_cell
;
1223 if (sc
->gc_verbose
) {
1225 sprintf(msg
,"done: %ld cells were recovered.\n", sc
->fcells
);
1230 static void finalize_cell(scheme
*sc
, pointer a
) {
1232 sc
->free(strvalue(a
));
1233 } else if(is_port(a
)) {
1234 if(a
->_object
._port
->kind
&port_file
1235 && a
->_object
._port
->rep
.stdio
.closeit
) {
1236 port_close(sc
,a
,port_input
|port_output
);
1238 sc
->free(a
->_object
._port
);
1242 /* ========== Routines for Reading ========== */
1244 static int file_push(scheme
*sc
, const char *fname
) {
1245 FILE *fin
=fopen(fname
,"r");
1248 sc
->load_stack
[sc
->file_i
].kind
=port_file
|port_input
;
1249 sc
->load_stack
[sc
->file_i
].rep
.stdio
.file
=fin
;
1250 sc
->load_stack
[sc
->file_i
].rep
.stdio
.closeit
=1;
1251 sc
->nesting_stack
[sc
->file_i
]=0;
1252 sc
->loadport
->_object
._port
=sc
->load_stack
+sc
->file_i
;
1257 static void file_pop(scheme
*sc
) {
1258 sc
->nesting
=sc
->nesting_stack
[sc
->file_i
];
1260 port_close(sc
,sc
->loadport
,port_input
);
1262 sc
->loadport
->_object
._port
=sc
->load_stack
+sc
->file_i
;
1263 if(file_interactive(sc
)) {
1269 static int file_interactive(scheme
*sc
) {
1270 return sc
->file_i
==0 && sc
->load_stack
[0].rep
.stdio
.file
==stdin
1271 && sc
->inport
->_object
._port
->kind
&port_file
;
1274 static port
*port_rep_from_filename(scheme
*sc
, const char *fn
, int prop
) {
1278 if(prop
==(port_input
|port_output
)) {
1280 } else if(prop
==port_output
) {
1289 pt
=port_rep_from_file(sc
,f
,prop
);
1290 pt
->rep
.stdio
.closeit
=1;
1294 static pointer
port_from_filename(scheme
*sc
, const char *fn
, int prop
) {
1296 pt
=port_rep_from_filename(sc
,fn
,prop
);
1300 return mk_port(sc
,pt
);
1303 static port
*port_rep_from_file(scheme
*sc
, FILE *f
, int prop
) {
1306 pt
=(port
*)sc
->malloc(sizeof(port
));
1310 if(prop
==(port_input
|port_output
)) {
1312 } else if(prop
==port_output
) {
1317 pt
->kind
=port_file
|prop
;
1318 pt
->rep
.stdio
.file
=f
;
1319 pt
->rep
.stdio
.closeit
=0;
1323 static pointer
port_from_file(scheme
*sc
, FILE *f
, int prop
) {
1325 pt
=port_rep_from_file(sc
,f
,prop
);
1329 return mk_port(sc
,pt
);
1332 static port
*port_rep_from_string(scheme
*sc
, char *start
, char *past_the_end
, int prop
) {
1334 pt
=(port
*)sc
->malloc(sizeof(port
));
1338 pt
->kind
=port_string
|prop
;
1339 pt
->rep
.string
.start
=start
;
1340 pt
->rep
.string
.curr
=start
;
1341 pt
->rep
.string
.past_the_end
=past_the_end
;
1345 static pointer
port_from_string(scheme
*sc
, char *start
, char *past_the_end
, int prop
) {
1347 pt
=port_rep_from_string(sc
,start
,past_the_end
,prop
);
1351 return mk_port(sc
,pt
);
1354 static void port_close(scheme
*sc
, pointer p
, int flag
) {
1355 port
*pt
=p
->_object
._port
;
1357 if((pt
->kind
& (port_input
|port_output
))==0) {
1358 if(pt
->kind
&port_file
) {
1359 fclose(pt
->rep
.stdio
.file
);
1365 /* get new character from input file */
1366 static int inchar(scheme
*sc
) {
1370 pt
=sc
->inport
->_object
._port
;
1372 if(c
==EOF
&& sc
->inport
==sc
->loadport
&& sc
->file_i
!=0) {
1374 if(sc
->nesting
!=0) {
1382 static int basic_inchar(port
*pt
) {
1383 if(pt
->kind
&port_file
) {
1384 return fgetc(pt
->rep
.stdio
.file
);
1386 if(*pt
->rep
.string
.curr
==0
1387 || pt
->rep
.string
.curr
==pt
->rep
.string
.past_the_end
) {
1390 return *pt
->rep
.string
.curr
++;
1395 /* back character to input buffer */
1396 static void backchar(scheme
*sc
, int c
) {
1399 pt
=sc
->inport
->_object
._port
;
1400 if(pt
->kind
&port_file
) {
1401 ungetc(c
,pt
->rep
.stdio
.file
);
1403 if(pt
->rep
.string
.curr
!=pt
->rep
.string
.start
) {
1404 --pt
->rep
.string
.curr
;
1409 INTERFACE
void putstr(scheme
*sc
, const char *s
) {
1410 port
*pt
=sc
->outport
->_object
._port
;
1411 if(pt
->kind
&port_file
) {
1412 fputs(s
,pt
->rep
.stdio
.file
);
1415 if(pt
->rep
.string
.curr
!=pt
->rep
.string
.past_the_end
) {
1416 *pt
->rep
.string
.curr
++=*s
;
1422 static void putchars(scheme
*sc
, const char *s
, int len
) {
1423 port
*pt
=sc
->outport
->_object
._port
;
1424 if(pt
->kind
&port_file
) {
1425 /* use the return value here to eliminate a compiler warning */
1426 if (fwrite(s
,1,len
,pt
->rep
.stdio
.file
) == 0)
1430 if(pt
->rep
.string
.curr
!=pt
->rep
.string
.past_the_end
) {
1431 *pt
->rep
.string
.curr
++=*s
++;
1437 INTERFACE
void putcharacter(scheme
*sc
, int c
) {
1438 port
*pt
=sc
->outport
->_object
._port
;
1439 if(pt
->kind
&port_file
) {
1440 fputc(c
,pt
->rep
.stdio
.file
);
1442 if(pt
->rep
.string
.curr
!=pt
->rep
.string
.past_the_end
) {
1443 *pt
->rep
.string
.curr
++=c
;
1448 /* read characters up to delimiter, but cater to character constants */
1449 static char *readstr_upto(scheme
*sc
, char *delim
) {
1450 char *p
= sc
->strbuff
;
1452 while (!is_one_of(delim
, (*p
++ = inchar(sc
))));
1453 if(p
==sc
->strbuff
+2 && p
[-2]=='\\') {
1462 /* read string expression "xxx...xxx" */
1463 static pointer
readstrexp(scheme
*sc
) {
1464 char *p
= sc
->strbuff
;
1467 enum { st_ok
, st_bsl
, st_x1
, st_x2
} state
=st_ok
;
1471 if(c
==EOF
|| p
-sc
->strbuff
>sizeof(sc
->strbuff
)-1) {
1482 return mk_counted_string(sc
,sc
->strbuff
,p
-sc
->strbuff
);
1520 if(c
>='0' && c
<='F') {
1524 c1
=(c1
<<4)+c
-'A'+10;
1540 /* check c is in chars */
1541 static INLINE
int is_one_of(char *s
, int c
) {
1542 if(c
==EOF
) return 1;
1549 /* skip white characters */
1550 static INLINE
void skipspace(scheme
*sc
) {
1552 while (isspace(c
=inchar(sc
)))
1560 static int token(scheme
*sc
) {
1563 switch (c
=inchar(sc
)) {
1567 return (TOK_LPAREN
);
1569 return (TOK_RPAREN
);
1572 if(is_one_of(" \n\t",c
)) {
1582 return (TOK_COMMENT
);
1584 return (TOK_DQUOTE
);
1586 return (TOK_BQUOTE
);
1588 if ((c
=inchar(sc
)) == '@')
1589 return (TOK_ATMARK
);
1598 } else if(c
== '!') {
1602 if(is_one_of(" tfodxb\\",c
)) {
1603 return TOK_SHARP_CONST
;
1614 /* ========== Routines for Printing ========== */
1615 #define ok_abbrev(x) (is_pair(x) && cdr(x) == sc->NIL)
1617 static void printslashstring(scheme
*sc
, char *p
, int len
) {
1619 unsigned char *s
=(unsigned char*)p
;
1620 putcharacter(sc
,'"');
1621 for ( i
=0; i
<len
; i
++) {
1622 if(*s
==0xff || *s
=='"' || *s
<' ' || *s
=='\\') {
1623 putcharacter(sc
,'\\');
1626 putcharacter(sc
,'"');
1629 putcharacter(sc
,'n');
1632 putcharacter(sc
,'t');
1635 putcharacter(sc
,'r');
1638 putcharacter(sc
,'\\');
1642 putcharacter(sc
,'x');
1644 putcharacter(sc
,d
+'0');
1646 putcharacter(sc
,d
-10+'A');
1650 putcharacter(sc
,d
+'0');
1652 putcharacter(sc
,d
-10+'A');
1657 putcharacter(sc
,*s
);
1661 putcharacter(sc
,'"');
1666 static void printatom(scheme
*sc
, pointer l
, int f
) {
1669 atom2str(sc
,l
,f
,&p
,&len
);
1674 /* Uses internal buffer unless string pointer is already available */
1675 static void atom2str(scheme
*sc
, pointer l
, int f
, char **pp
, int *plen
) {
1680 } else if (l
== sc
->T
) {
1682 } else if (l
== sc
->F
) {
1684 } else if (l
== sc
->EOF_OBJ
) {
1686 } else if (is_port(l
)) {
1688 strcpy(p
, "#<PORT>");
1689 } else if (is_number(l
)) {
1692 sprintf(p
, "%ld", ivalue_unchecked(l
));
1694 sprintf(p
, "%.10g", rvalue_unchecked(l
));
1696 } else if (is_string(l
)) {
1699 } else { /* Hack, uses the fact that printing is needed */
1702 printslashstring(sc
, strvalue(l
), strlength(l
));
1705 } else if (is_character(l
)) {
1714 sprintf(p
,"#\\space"); break;
1716 sprintf(p
,"#\\newline"); break;
1718 sprintf(p
,"#\\return"); break;
1720 sprintf(p
,"#\\tab"); break;
1724 strcpy(p
,"#\\del"); break;
1726 strcpy(p
,"#\\"); strcat(p
,charnames
[c
]); break;
1730 sprintf(p
,"#\\x%x",c
); break;
1733 sprintf(p
,"#\\%c",c
); break;
1736 } else if (is_symbol(l
)) {
1738 } else if (is_proc(l
)) {
1740 sprintf(p
, "#<%s PROCEDURE %ld>", procname(l
),procnum(l
));
1741 } else if (is_macro(l
)) {
1743 } else if (is_closure(l
)) {
1745 } else if (is_promise(l
)) {
1747 } else if (is_foreign(l
)) {
1749 sprintf(p
, "#<FOREIGN PROCEDURE %ld>", procnum(l
));
1750 } else if (is_continuation(l
)) {
1751 p
= "#<CONTINUATION>";
1758 /* ========== Routines for Evaluation Cycle ========== */
1760 /* make closure. c is code. e is environment */
1761 static pointer
mk_closure(scheme
*sc
, pointer c
, pointer e
) {
1762 pointer x
= get_cell(sc
, c
, e
);
1764 typeflag(x
) = T_CLOSURE
;
1770 /* make continuation. */
1771 static pointer
mk_continuation(scheme
*sc
, pointer d
) {
1772 pointer x
= get_cell(sc
, sc
->NIL
, d
);
1774 typeflag(x
) = T_CONTINUATION
;
1779 static pointer
list_star(scheme
*sc
, pointer d
) {
1781 if(cdr(d
)==sc
->NIL
) {
1784 p
=cons(sc
,car(d
),cdr(d
));
1786 while(cdr(cdr(p
))!=sc
->NIL
) {
1787 d
=cons(sc
,car(p
),cdr(p
));
1788 if(cdr(cdr(p
))!=sc
->NIL
) {
1796 /* reverse list -- produce new list */
1797 static pointer
reverse(scheme
*sc
, pointer a
) {
1798 /* a must be checked by gc */
1799 pointer p
= sc
->NIL
;
1801 for ( ; is_pair(a
); a
= cdr(a
)) {
1802 p
= cons(sc
, car(a
), p
);
1807 /* reverse list --- in-place */
1808 static pointer
reverse_in_place(scheme
*sc
, pointer term
, pointer list
) {
1809 pointer p
= list
, result
= term
, q
;
1811 while (p
!= sc
->NIL
) {
1820 /* append list -- produce new list */
1821 static pointer
append(scheme
*sc
, pointer a
, pointer b
) {
1826 while (a
!= sc
->NIL
) {
1836 /* equivalence of atoms */
1837 static int eqv(pointer a
, pointer b
) {
1840 return (strvalue(a
) == strvalue(b
));
1843 } else if (is_number(a
)) {
1845 return num_eq(nvalue(a
),nvalue(b
));
1848 } else if (is_character(a
)) {
1849 if (is_character(b
))
1850 return charvalue(a
)==charvalue(b
);
1853 } else if (is_port(a
)) {
1858 } else if (is_proc(a
)) {
1860 return procnum(a
)==procnum(b
);
1868 /* true or false value macro */
1869 /* () is #t in R5RS */
1870 #define is_true(p) ((p) != sc->F)
1871 #define is_false(p) ((p) == sc->F)
1873 /* ========== Environment implementation ========== */
1875 #if !defined(USE_ALIST_ENV) || !defined(USE_OBJECT_LIST)
1877 static int hash_fn(const char *key
, int table_size
)
1879 unsigned int hashed
= 0;
1881 int bits_per_int
= sizeof(unsigned int)*8;
1883 for (c
= key
; *c
; c
++) {
1884 /* letters have about 5 bits in them */
1885 hashed
= (hashed
<<5) | (hashed
>>(bits_per_int
-5));
1888 return hashed
% table_size
;
1892 #ifndef USE_ALIST_ENV
1895 * In this implementation, each frame of the environment may be
1896 * a hash table: a vector of alists hashed by variable name.
1897 * In practice, we use a vector only for the initial frame;
1898 * subsequent frames are too small and transient for the lookup
1899 * speed to out-weigh the cost of making a new vector.
1902 static void new_frame_in_env(scheme
*sc
, pointer old_env
)
1906 /* The interaction-environment has about 300 variables in it. */
1907 if (old_env
== sc
->NIL
) {
1908 new_frame
= mk_vector(sc
, 461);
1910 new_frame
= sc
->NIL
;
1913 sc
->envir
= immutable_cons(sc
, new_frame
, old_env
);
1914 setenvironment(sc
->envir
);
1917 static INLINE
void new_slot_spec_in_env(scheme
*sc
, pointer env
,
1918 pointer variable
, pointer value
)
1920 pointer slot
= immutable_cons(sc
, variable
, value
);
1922 if (is_vector(car(env
))) {
1923 int location
= hash_fn(symname(variable
), ivalue_unchecked(car(env
)));
1925 set_vector_elem(car(env
), location
,
1926 immutable_cons(sc
, slot
, vector_elem(car(env
), location
)));
1928 car(env
) = immutable_cons(sc
, slot
, car(env
));
1932 static pointer
find_slot_in_env(scheme
*sc
, pointer env
, pointer hdl
, int all
)
1934 pointer x
= sc
->NIL
, y
= sc
->NIL
;
1937 for (x
= env
; x
!= sc
->NIL
; x
= cdr(x
)) {
1938 if (is_vector(car(x
))) {
1939 location
= hash_fn(symname(hdl
), ivalue_unchecked(car(x
)));
1940 y
= vector_elem(car(x
), location
);
1944 for ( ; y
!= sc
->NIL
; y
= cdr(y
)) {
1945 if (caar(y
) == hdl
) {
1962 #else /* USE_ALIST_ENV */
1964 static INLINE
void new_frame_in_env(scheme
*sc
, pointer old_env
)
1966 sc
->envir
= immutable_cons(sc
, sc
->NIL
, old_env
);
1967 setenvironment(sc
->envir
);
1970 static INLINE
void new_slot_spec_in_env(scheme
*sc
, pointer env
,
1971 pointer variable
, pointer value
)
1973 car(env
) = immutable_cons(sc
, immutable_cons(sc
, variable
, value
), car(env
));
1976 static pointer
find_slot_in_env(scheme
*sc
, pointer env
, pointer hdl
, int all
)
1979 for (x
= env
; x
!= sc
->NIL
; x
= cdr(x
)) {
1980 for (y
= car(x
); y
!= sc
->NIL
; y
= cdr(y
)) {
1981 if (caar(y
) == hdl
) {
1998 #endif /* USE_ALIST_ENV else */
2000 static INLINE
void new_slot_in_env(scheme
*sc
, pointer variable
, pointer value
)
2002 new_slot_spec_in_env(sc
, sc
->envir
, variable
, value
);
2005 static INLINE
void set_slot_in_env(scheme
*sc
, pointer slot
, pointer value
)
2010 static INLINE pointer
slot_value_in_env(pointer slot
)
2015 /* ========== Evaluation Cycle ========== */
2018 static pointer
_Error_1(scheme
*sc
, const char *s
, pointer a
) {
2021 pointer hdl
=sc
->ERROR_HOOK
;
2023 x
=find_slot_in_env(sc
,sc
->envir
,hdl
,1);
2026 sc
->code
= cons(sc
, cons(sc
, sc
->QUOTE
, cons(sc
,(a
), sc
->NIL
)), sc
->NIL
);
2030 sc
->code
= cons(sc
, mk_string(sc
, (s
)), sc
->code
);
2031 setimmutable(car(sc
->code
));
2032 sc
->code
= cons(sc
, slot_value_in_env(x
), sc
->code
);
2033 sc
->op
= (int)OP_EVAL
;
2039 sc
->args
= cons(sc
, (a
), sc
->NIL
);
2043 sc
->args
= cons(sc
, mk_string(sc
, (s
)), sc
->args
);
2044 setimmutable(car(sc
->args
));
2045 sc
->op
= (int)OP_ERR0
;
2048 #define Error_1(sc,s, a) return _Error_1(sc,s,a)
2049 #define Error_0(sc,s) return _Error_1(sc,s,0)
2051 /* Too small to turn into function */
2053 # define END } while (0)
2054 #define s_goto(sc,a) BEGIN \
2055 sc->op = (int)(a); \
2058 #define s_return(sc,a) return _s_return(sc,a)
2060 #ifndef USE_SCHEME_STACK
2062 /* this structure holds all the interpreter's registers */
2063 struct dump_stack_frame
{
2064 enum scheme_opcodes op
;
2070 #define STACK_GROWTH 3
2072 static void s_save(scheme
*sc
, enum scheme_opcodes op
, pointer args
, pointer code
)
2074 long nframes
= (long)sc
->dump
;
2075 struct dump_stack_frame
*next_frame
;
2077 /* enough room for the next frame? */
2078 if (nframes
>= sc
->dump_size
) {
2079 sc
->dump_size
+= STACK_GROWTH
;
2080 /* alas there is no sc->realloc */
2081 sc
->dump_base
= realloc(sc
->dump_base
,
2082 sizeof(struct dump_stack_frame
) * sc
->dump_size
);
2084 next_frame
= (struct dump_stack_frame
*)sc
->dump_base
+ nframes
;
2085 next_frame
->op
= op
;
2086 next_frame
->args
= args
;
2087 next_frame
->envir
= sc
->envir
;
2088 next_frame
->code
= code
;
2089 sc
->dump
= (pointer
)(nframes
+1L);
2092 static pointer
_s_return(scheme
*sc
, pointer a
)
2094 long nframes
= (long)sc
->dump
;
2095 struct dump_stack_frame
*frame
;
2102 frame
= (struct dump_stack_frame
*)sc
->dump_base
+ nframes
;
2104 sc
->args
= frame
->args
;
2105 sc
->envir
= frame
->envir
;
2106 sc
->code
= frame
->code
;
2107 sc
->dump
= (pointer
)nframes
;
2111 static INLINE
void dump_stack_reset(scheme
*sc
)
2113 /* in this implementation, sc->dump is the number of frames on the stack */
2114 sc
->dump
= (pointer
)0;
2117 static INLINE
void dump_stack_initialize(scheme
*sc
)
2120 sc
->dump_base
= NULL
;
2121 dump_stack_reset(sc
);
2124 static void dump_stack_free(scheme
*sc
)
2126 free(sc
->dump_base
);
2127 sc
->dump_base
= NULL
;
2128 sc
->dump
= (pointer
)0;
2132 static INLINE
void dump_stack_mark(scheme
*sc
)
2134 long nframes
= (long)sc
->dump
;
2136 for(i
=0; i
<nframes
; i
++) {
2137 struct dump_stack_frame
*frame
;
2138 frame
= (struct dump_stack_frame
*)sc
->dump_base
+ i
;
2147 static INLINE
void dump_stack_reset(scheme
*sc
)
2152 static INLINE
void dump_stack_initialize(scheme
*sc
)
2154 dump_stack_reset(sc
);
2157 static void dump_stack_free(scheme
*sc
)
2162 static pointer
_s_return(scheme
*sc
, pointer a
) {
2164 if(sc
->dump
==sc
->NIL
) return sc
->NIL
;
2165 sc
->op
= ivalue(car(sc
->dump
));
2166 sc
->args
= cadr(sc
->dump
);
2167 sc
->envir
= caddr(sc
->dump
);
2168 sc
->code
= cadddr(sc
->dump
);
2169 sc
->dump
= cddddr(sc
->dump
);
2173 static void s_save(scheme
*sc
, enum scheme_opcodes op
, pointer args
, pointer code
) {
2174 sc
->dump
= cons(sc
, sc
->envir
, cons(sc
, (code
), sc
->dump
));
2175 sc
->dump
= cons(sc
, (args
), sc
->dump
);
2176 sc
->dump
= cons(sc
, mk_integer(sc
, (long)(op
)), sc
->dump
);
2179 static INLINE
void dump_stack_mark(scheme
*sc
)
2185 #define s_retbool(tf) s_return(sc,(tf) ? sc->T : sc->F)
2187 static pointer
opexe_0(scheme
*sc
, enum scheme_opcodes op
) {
2191 case OP_LOAD
: /* load */
2192 if(file_interactive(sc
)) {
2193 fprintf(sc
->outport
->_object
._port
->rep
.stdio
.file
,
2194 "Loading %s\n", strvalue(car(sc
->args
)));
2196 if (!file_push(sc
,strvalue(car(sc
->args
)))) {
2197 Error_1(sc
,"unable to open", car(sc
->args
));
2199 s_goto(sc
,OP_T0LVL
);
2201 case OP_T0LVL
: /* top level */
2202 if(file_interactive(sc
)) {
2206 dump_stack_reset(sc
);
2207 sc
->envir
= sc
->global_env
;
2208 sc
->save_inport
=sc
->inport
;
2209 sc
->inport
= sc
->loadport
;
2210 s_save(sc
,OP_T0LVL
, sc
->NIL
, sc
->NIL
);
2211 s_save(sc
,OP_VALUEPRINT
, sc
->NIL
, sc
->NIL
);
2212 s_save(sc
,OP_T1LVL
, sc
->NIL
, sc
->NIL
);
2213 if (file_interactive(sc
)) {
2216 s_goto(sc
,OP_READ_INTERNAL
);
2218 case OP_T1LVL
: /* top level */
2219 sc
->code
= sc
->value
;
2220 sc
->inport
=sc
->save_inport
;
2223 case OP_READ_INTERNAL
: /* internal read */
2224 sc
->tok
= token(sc
);
2225 if(sc
->tok
==TOK_EOF
) {
2226 if(sc
->inport
==sc
->loadport
) {
2230 s_return(sc
,sc
->EOF_OBJ
);
2233 s_goto(sc
,OP_RDSEXPR
);
2236 s_return(sc
, gensym(sc
));
2238 case OP_VALUEPRINT
: /* print evaluation result */
2239 /* OP_VALUEPRINT is always pushed, because when changing from
2240 non-interactive to interactive mode, it needs to be
2241 already on the stack */
2243 putstr(sc
,"\nGives: ");
2245 if(file_interactive(sc
)) {
2247 sc
->args
= sc
->value
;
2248 s_goto(sc
,OP_P0LIST
);
2250 s_return(sc
,sc
->value
);
2253 case OP_EVAL
: /* main part of evaluation */
2256 /*s_save(sc,OP_VALUEPRINT,sc->NIL,sc->NIL);*/
2257 s_save(sc
,OP_REAL_EVAL
,sc
->args
,sc
->code
);
2259 putstr(sc
,"\nEval: ");
2260 s_goto(sc
,OP_P0LIST
);
2265 if (is_symbol(sc
->code
)) { /* symbol */
2266 x
=find_slot_in_env(sc
,sc
->envir
,sc
->code
,1);
2268 s_return(sc
,slot_value_in_env(x
));
2270 Error_1(sc
,"eval: unbound variable:", sc
->code
);
2272 } else if (is_pair(sc
->code
)) {
2273 if (is_syntax(x
= car(sc
->code
))) { /* SYNTAX */
2274 sc
->code
= cdr(sc
->code
);
2275 s_goto(sc
,syntaxnum(x
));
2276 } else {/* first, eval top element and eval arguments */
2277 s_save(sc
,OP_E0ARGS
, sc
->NIL
, sc
->code
);
2278 /* If no macros => s_save(sc,OP_E1ARGS, sc->NIL, cdr(sc->code));*/
2279 sc
->code
= car(sc
->code
);
2283 s_return(sc
,sc
->code
);
2286 case OP_E0ARGS
: /* eval arguments */
2287 if (is_macro(sc
->value
)) { /* macro expansion */
2288 s_save(sc
,OP_DOMACRO
, sc
->NIL
, sc
->NIL
);
2289 sc
->args
= cons(sc
,sc
->code
, sc
->NIL
);
2290 sc
->code
= sc
->value
;
2291 s_goto(sc
,OP_APPLY
);
2293 sc
->code
= cdr(sc
->code
);
2294 s_goto(sc
,OP_E1ARGS
);
2297 case OP_E1ARGS
: /* eval arguments */
2298 sc
->args
= cons(sc
, sc
->value
, sc
->args
);
2299 if (is_pair(sc
->code
)) { /* continue */
2300 s_save(sc
,OP_E1ARGS
, sc
->args
, cdr(sc
->code
));
2301 sc
->code
= car(sc
->code
);
2305 sc
->args
= reverse_in_place(sc
, sc
->NIL
, sc
->args
);
2306 sc
->code
= car(sc
->args
);
2307 sc
->args
= cdr(sc
->args
);
2308 s_goto(sc
,OP_APPLY
);
2314 sc
->tracing
=ivalue(car(sc
->args
));
2315 s_return(sc
,mk_integer(sc
,tr
));
2319 case OP_APPLY
: /* apply 'code' to 'args' */
2322 s_save(sc
,OP_REAL_APPLY
,sc
->args
,sc
->code
);
2324 /* sc->args=cons(sc,sc->code,sc->args);*/
2325 putstr(sc
,"\nApply to: ");
2326 s_goto(sc
,OP_P0LIST
);
2331 if (is_proc(sc
->code
)) {
2332 s_goto(sc
,procnum(sc
->code
)); /* PROCEDURE */
2333 } else if (is_foreign(sc
->code
)) {
2334 x
=sc
->code
->_object
._ff(sc
,sc
->args
);
2336 } else if (is_closure(sc
->code
) || is_macro(sc
->code
)
2337 || is_promise(sc
->code
)) { /* CLOSURE */
2338 /* Should not accept promise */
2339 /* make environment */
2340 new_frame_in_env(sc
, closure_env(sc
->code
));
2341 for (x
= car(closure_code(sc
->code
)), y
= sc
->args
;
2342 is_pair(x
); x
= cdr(x
), y
= cdr(y
)) {
2344 Error_0(sc
,"not enough arguments");
2346 new_slot_in_env(sc
, car(x
), car(y
));
2351 * if (y != sc->NIL) {
2352 * Error_0(sc,"too many arguments");
2355 } else if (is_symbol(x
))
2356 new_slot_in_env(sc
, x
, y
);
2358 Error_1(sc
,"syntax error in closure: not a symbol:", x
);
2360 sc
->code
= cdr(closure_code(sc
->code
));
2362 s_goto(sc
,OP_BEGIN
);
2363 } else if (is_continuation(sc
->code
)) { /* CONTINUATION */
2364 sc
->dump
= cont_dump(sc
->code
);
2365 s_return(sc
,sc
->args
!= sc
->NIL
? car(sc
->args
) : sc
->NIL
);
2367 Error_0(sc
,"illegal function");
2370 case OP_DOMACRO
: /* do macro */
2371 sc
->code
= sc
->value
;
2374 case OP_LAMBDA
: /* lambda */
2375 s_return(sc
,mk_closure(sc
, sc
->code
, sc
->envir
));
2377 case OP_MKCLOSURE
: /* make-closure */
2379 if(car(x
)==sc
->LAMBDA
) {
2382 if(cdr(sc
->args
)==sc
->NIL
) {
2387 s_return(sc
,mk_closure(sc
, x
, y
));
2389 case OP_QUOTE
: /* quote */
2391 s_return(sc
,car(sc
->code
));
2393 case OP_DEF0
: /* define */
2394 if (is_pair(car(sc
->code
))) {
2396 sc
->code
= cons(sc
, sc
->LAMBDA
, cons(sc
, cdar(sc
->code
), cdr(sc
->code
)));
2399 sc
->code
= cadr(sc
->code
);
2401 if (!is_symbol(x
)) {
2402 Error_0(sc
,"variable is not a symbol");
2404 s_save(sc
,OP_DEF1
, sc
->NIL
, x
);
2407 case OP_DEF1
: /* define */
2408 x
=find_slot_in_env(sc
,sc
->envir
,sc
->code
,0);
2410 set_slot_in_env(sc
, x
, sc
->value
);
2412 new_slot_in_env(sc
, sc
->code
, sc
->value
);
2414 s_return(sc
,sc
->code
);
2417 case OP_DEFP
: /* defined? */
2419 if(cdr(sc
->args
)!=sc
->NIL
) {
2422 s_retbool(find_slot_in_env(sc
,x
,car(sc
->args
),1)!=sc
->NIL
);
2424 case OP_SET0
: /* set! */
2425 s_save(sc
,OP_SET1
, sc
->NIL
, car(sc
->code
));
2426 sc
->code
= cadr(sc
->code
);
2429 case OP_SET1
: /* set! */
2430 y
=find_slot_in_env(sc
,sc
->envir
,sc
->code
,1);
2432 set_slot_in_env(sc
, y
, sc
->value
);
2433 s_return(sc
,sc
->value
);
2435 Error_1(sc
,"set!: unbound variable:", sc
->code
);
2439 case OP_BEGIN
: /* begin */
2440 if (!is_pair(sc
->code
)) {
2441 s_return(sc
,sc
->code
);
2443 if (cdr(sc
->code
) != sc
->NIL
) {
2444 s_save(sc
,OP_BEGIN
, sc
->NIL
, cdr(sc
->code
));
2446 sc
->code
= car(sc
->code
);
2449 case OP_IF0
: /* if */
2450 s_save(sc
,OP_IF1
, sc
->NIL
, cdr(sc
->code
));
2451 sc
->code
= car(sc
->code
);
2454 case OP_IF1
: /* if */
2455 if (is_true(sc
->value
))
2456 sc
->code
= car(sc
->code
);
2458 sc
->code
= cadr(sc
->code
); /* (if #f 1) ==> () because
2459 * car(sc->NIL) = sc->NIL */
2462 case OP_LET0
: /* let */
2464 sc
->value
= sc
->code
;
2465 sc
->code
= is_symbol(car(sc
->code
)) ? cadr(sc
->code
) : car(sc
->code
);
2468 case OP_LET1
: /* let (calculate parameters) */
2469 sc
->args
= cons(sc
, sc
->value
, sc
->args
);
2470 if (is_pair(sc
->code
)) { /* continue */
2471 s_save(sc
,OP_LET1
, sc
->args
, cdr(sc
->code
));
2472 sc
->code
= cadar(sc
->code
);
2476 sc
->args
= reverse_in_place(sc
, sc
->NIL
, sc
->args
);
2477 sc
->code
= car(sc
->args
);
2478 sc
->args
= cdr(sc
->args
);
2482 case OP_LET2
: /* let */
2483 new_frame_in_env(sc
, sc
->envir
);
2484 for (x
= is_symbol(car(sc
->code
)) ? cadr(sc
->code
) : car(sc
->code
), y
= sc
->args
;
2485 y
!= sc
->NIL
; x
= cdr(x
), y
= cdr(y
)) {
2486 new_slot_in_env(sc
, caar(x
), car(y
));
2488 if (is_symbol(car(sc
->code
))) { /* named let */
2489 for (x
= cadr(sc
->code
), sc
->args
= sc
->NIL
; x
!= sc
->NIL
; x
= cdr(x
)) {
2491 sc
->args
= cons(sc
, caar(x
), sc
->args
);
2493 x
= mk_closure(sc
, cons(sc
, reverse_in_place(sc
, sc
->NIL
, sc
->args
), cddr(sc
->code
)), sc
->envir
);
2494 new_slot_in_env(sc
, car(sc
->code
), x
);
2495 sc
->code
= cddr(sc
->code
);
2498 sc
->code
= cdr(sc
->code
);
2501 s_goto(sc
,OP_BEGIN
);
2503 case OP_LET0AST
: /* let* */
2504 if (car(sc
->code
) == sc
->NIL
) {
2505 new_frame_in_env(sc
, sc
->envir
);
2506 sc
->code
= cdr(sc
->code
);
2507 s_goto(sc
,OP_BEGIN
);
2509 s_save(sc
,OP_LET1AST
, cdr(sc
->code
), car(sc
->code
));
2510 sc
->code
= cadaar(sc
->code
);
2513 case OP_LET1AST
: /* let* (make new frame) */
2514 new_frame_in_env(sc
, sc
->envir
);
2515 s_goto(sc
,OP_LET2AST
);
2517 case OP_LET2AST
: /* let* (calculate parameters) */
2518 new_slot_in_env(sc
, caar(sc
->code
), sc
->value
);
2519 sc
->code
= cdr(sc
->code
);
2520 if (is_pair(sc
->code
)) { /* continue */
2521 s_save(sc
,OP_LET2AST
, sc
->args
, sc
->code
);
2522 sc
->code
= cadar(sc
->code
);
2526 sc
->code
= sc
->args
;
2528 s_goto(sc
,OP_BEGIN
);
2531 sprintf(sc
->strbuff
, "%d: illegal operator", sc
->op
);
2532 Error_0(sc
,sc
->strbuff
);
2537 static pointer
opexe_1(scheme
*sc
, enum scheme_opcodes op
) {
2541 case OP_LET0REC
: /* letrec */
2542 new_frame_in_env(sc
, sc
->envir
);
2544 sc
->value
= sc
->code
;
2545 sc
->code
= car(sc
->code
);
2546 s_goto(sc
,OP_LET1REC
);
2548 case OP_LET1REC
: /* letrec (calculate parameters) */
2549 sc
->args
= cons(sc
, sc
->value
, sc
->args
);
2550 if (is_pair(sc
->code
)) { /* continue */
2551 s_save(sc
,OP_LET1REC
, sc
->args
, cdr(sc
->code
));
2552 sc
->code
= cadar(sc
->code
);
2556 sc
->args
= reverse_in_place(sc
, sc
->NIL
, sc
->args
);
2557 sc
->code
= car(sc
->args
);
2558 sc
->args
= cdr(sc
->args
);
2559 s_goto(sc
,OP_LET2REC
);
2562 case OP_LET2REC
: /* letrec */
2563 for (x
= car(sc
->code
), y
= sc
->args
; y
!= sc
->NIL
; x
= cdr(x
), y
= cdr(y
)) {
2564 new_slot_in_env(sc
, caar(x
), car(y
));
2566 sc
->code
= cdr(sc
->code
);
2568 s_goto(sc
,OP_BEGIN
);
2570 case OP_COND0
: /* cond */
2571 if (!is_pair(sc
->code
)) {
2572 Error_0(sc
,"syntax error in cond");
2574 s_save(sc
,OP_COND1
, sc
->NIL
, sc
->code
);
2575 sc
->code
= caar(sc
->code
);
2578 case OP_COND1
: /* cond */
2579 if (is_true(sc
->value
)) {
2580 if ((sc
->code
= cdar(sc
->code
)) == sc
->NIL
) {
2581 s_return(sc
,sc
->value
);
2583 if(car(sc
->code
)==sc
->FEED_TO
) {
2584 if(!is_pair(cdr(sc
->code
))) {
2585 Error_0(sc
,"syntax error in cond");
2587 x
=cons(sc
, sc
->QUOTE
, cons(sc
, sc
->value
, sc
->NIL
));
2588 sc
->code
=cons(sc
,cadr(sc
->code
),cons(sc
,x
,sc
->NIL
));
2591 s_goto(sc
,OP_BEGIN
);
2593 if ((sc
->code
= cdr(sc
->code
)) == sc
->NIL
) {
2594 s_return(sc
,sc
->NIL
);
2596 s_save(sc
,OP_COND1
, sc
->NIL
, sc
->code
);
2597 sc
->code
= caar(sc
->code
);
2602 case OP_DELAY
: /* delay */
2603 x
= mk_closure(sc
, cons(sc
, sc
->NIL
, sc
->code
), sc
->envir
);
2604 typeflag(x
)=T_PROMISE
;
2607 case OP_AND0
: /* and */
2608 if (sc
->code
== sc
->NIL
) {
2611 s_save(sc
,OP_AND1
, sc
->NIL
, cdr(sc
->code
));
2612 sc
->code
= car(sc
->code
);
2615 case OP_AND1
: /* and */
2616 if (is_false(sc
->value
)) {
2617 s_return(sc
,sc
->value
);
2618 } else if (sc
->code
== sc
->NIL
) {
2619 s_return(sc
,sc
->value
);
2621 s_save(sc
,OP_AND1
, sc
->NIL
, cdr(sc
->code
));
2622 sc
->code
= car(sc
->code
);
2626 case OP_OR0
: /* or */
2627 if (sc
->code
== sc
->NIL
) {
2630 s_save(sc
,OP_OR1
, sc
->NIL
, cdr(sc
->code
));
2631 sc
->code
= car(sc
->code
);
2634 case OP_OR1
: /* or */
2635 if (is_true(sc
->value
)) {
2636 s_return(sc
,sc
->value
);
2637 } else if (sc
->code
== sc
->NIL
) {
2638 s_return(sc
,sc
->value
);
2640 s_save(sc
,OP_OR1
, sc
->NIL
, cdr(sc
->code
));
2641 sc
->code
= car(sc
->code
);
2645 case OP_C0STREAM
: /* cons-stream */
2646 s_save(sc
,OP_C1STREAM
, sc
->NIL
, cdr(sc
->code
));
2647 sc
->code
= car(sc
->code
);
2650 case OP_C1STREAM
: /* cons-stream */
2651 sc
->args
= sc
->value
; /* save sc->value to register sc->args for gc */
2652 x
= mk_closure(sc
, cons(sc
, sc
->NIL
, sc
->code
), sc
->envir
);
2653 typeflag(x
)=T_PROMISE
;
2654 s_return(sc
,cons(sc
, sc
->args
, x
));
2656 case OP_MACRO0
: /* macro */
2657 if (is_pair(car(sc
->code
))) {
2659 sc
->code
= cons(sc
, sc
->LAMBDA
, cons(sc
, cdar(sc
->code
), cdr(sc
->code
)));
2662 sc
->code
= cadr(sc
->code
);
2664 if (!is_symbol(x
)) {
2665 Error_0(sc
,"variable is not a symbol");
2667 s_save(sc
,OP_MACRO1
, sc
->NIL
, x
);
2670 case OP_MACRO1
: /* macro */
2671 typeflag(sc
->value
) = T_MACRO
;
2672 x
= find_slot_in_env(sc
, sc
->envir
, sc
->code
, 0);
2674 set_slot_in_env(sc
, x
, sc
->value
);
2676 new_slot_in_env(sc
, sc
->code
, sc
->value
);
2678 s_return(sc
,sc
->code
);
2680 case OP_CASE0
: /* case */
2681 s_save(sc
,OP_CASE1
, sc
->NIL
, cdr(sc
->code
));
2682 sc
->code
= car(sc
->code
);
2685 case OP_CASE1
: /* case */
2686 for (x
= sc
->code
; x
!= sc
->NIL
; x
= cdr(x
)) {
2687 if (!is_pair(y
= caar(x
))) {
2690 for ( ; y
!= sc
->NIL
; y
= cdr(y
)) {
2691 if (eqv(car(y
), sc
->value
)) {
2700 if (is_pair(caar(x
))) {
2702 s_goto(sc
,OP_BEGIN
);
2704 s_save(sc
,OP_CASE2
, sc
->NIL
, cdar(x
));
2709 s_return(sc
,sc
->NIL
);
2712 case OP_CASE2
: /* case */
2713 if (is_true(sc
->value
)) {
2714 s_goto(sc
,OP_BEGIN
);
2716 s_return(sc
,sc
->NIL
);
2719 case OP_PAPPLY
: /* apply */
2720 sc
->code
= car(sc
->args
);
2721 sc
->args
= list_star(sc
,cdr(sc
->args
));
2722 /*sc->args = cadr(sc->args);*/
2723 s_goto(sc
,OP_APPLY
);
2725 case OP_PEVAL
: /* eval */
2726 if(cdr(sc
->args
)!=sc
->NIL
) {
2727 sc
->envir
=cadr(sc
->args
);
2729 sc
->code
= car(sc
->args
);
2732 case OP_CONTINUATION
: /* call-with-current-continuation */
2733 sc
->code
= car(sc
->args
);
2734 sc
->args
= cons(sc
, mk_continuation(sc
, sc
->dump
), sc
->NIL
);
2735 s_goto(sc
,OP_APPLY
);
2738 sprintf(sc
->strbuff
, "%d: illegal operator", sc
->op
);
2739 Error_0(sc
,sc
->strbuff
);
2744 static pointer
opexe_2(scheme
*sc
, enum scheme_opcodes op
) {
2753 case OP_INEX2EX
: /* inexact->exact */
2757 } else if(modf(rvalue_unchecked(x
),&dd
)==0.0) {
2758 s_return(sc
,mk_integer(sc
,ivalue(x
)));
2760 Error_1(sc
,"inexact->exact: not integral:",x
);
2765 s_return(sc
, mk_real(sc
, exp(rvalue(x
))));
2769 s_return(sc
, mk_real(sc
, log(rvalue(x
))));
2773 s_return(sc
, mk_real(sc
, sin(rvalue(x
))));
2777 s_return(sc
, mk_real(sc
, cos(rvalue(x
))));
2781 s_return(sc
, mk_real(sc
, tan(rvalue(x
))));
2785 s_return(sc
, mk_real(sc
, asin(rvalue(x
))));
2789 s_return(sc
, mk_real(sc
, acos(rvalue(x
))));
2793 if(cdr(sc
->args
)==sc
->NIL
) {
2794 s_return(sc
, mk_real(sc
, atan(rvalue(x
))));
2796 pointer y
=cadr(sc
->args
);
2797 s_return(sc
, mk_real(sc
, atan2(rvalue(x
),rvalue(y
))));
2802 s_return(sc
, mk_real(sc
, sqrt(rvalue(x
))));
2806 if(cdr(sc
->args
)==sc
->NIL
) {
2807 Error_0(sc
,"expt: needs two arguments");
2809 pointer y
=cadr(sc
->args
);
2810 s_return(sc
, mk_real(sc
, pow(rvalue(x
),rvalue(y
))));
2815 s_return(sc
, mk_real(sc
, floor(rvalue(x
))));
2819 s_return(sc
, mk_real(sc
, ceil(rvalue(x
))));
2821 case OP_TRUNCATE
: {
2822 double rvalue_of_x
;
2824 rvalue_of_x
= rvalue(x
) ;
2825 if (rvalue_of_x
> 0) {
2826 s_return(sc
, mk_real(sc
, floor(rvalue_of_x
)));
2828 s_return(sc
, mk_real(sc
, ceil(rvalue_of_x
)));
2834 s_return(sc
, mk_real(sc
, round_per_R5RS(rvalue(x
))));
2837 case OP_ADD
: /* + */
2839 for (x
= sc
->args
; x
!= sc
->NIL
; x
= cdr(x
)) {
2840 v
=num_add(v
,nvalue(car(x
)));
2842 s_return(sc
,mk_number(sc
, v
));
2844 case OP_MUL
: /* * */
2846 for (x
= sc
->args
; x
!= sc
->NIL
; x
= cdr(x
)) {
2847 v
=num_mul(v
,nvalue(car(x
)));
2849 s_return(sc
,mk_number(sc
, v
));
2851 case OP_SUB
: /* - */
2852 if(cdr(sc
->args
)==sc
->NIL
) {
2857 v
= nvalue(car(sc
->args
));
2859 for (; x
!= sc
->NIL
; x
= cdr(x
)) {
2860 v
=num_sub(v
,nvalue(car(x
)));
2862 s_return(sc
,mk_number(sc
, v
));
2864 case OP_DIV
: /* / */
2865 if(cdr(sc
->args
)==sc
->NIL
) {
2870 v
= nvalue(car(sc
->args
));
2872 for (; x
!= sc
->NIL
; x
= cdr(x
)) {
2873 if (!is_zero_double(rvalue(car(x
))))
2874 v
=num_div(v
,nvalue(car(x
)));
2876 Error_0(sc
,"/: division by zero");
2879 s_return(sc
,mk_number(sc
, v
));
2881 case OP_INTDIV
: /* quotient */
2882 if(cdr(sc
->args
)==sc
->NIL
) {
2887 v
= nvalue(car(sc
->args
));
2889 for (; x
!= sc
->NIL
; x
= cdr(x
)) {
2890 if (ivalue(car(x
)) != 0)
2891 v
=num_intdiv(v
,nvalue(car(x
)));
2893 Error_0(sc
,"quotient: division by zero");
2896 s_return(sc
,mk_number(sc
, v
));
2898 case OP_REM
: /* remainder */
2899 v
= nvalue(car(sc
->args
));
2900 if (ivalue(cadr(sc
->args
)) != 0)
2901 v
=num_rem(v
,nvalue(cadr(sc
->args
)));
2903 Error_0(sc
,"remainder: division by zero");
2905 s_return(sc
,mk_number(sc
, v
));
2907 case OP_MOD
: /* modulo */
2908 v
= nvalue(car(sc
->args
));
2909 if (ivalue(cadr(sc
->args
)) != 0)
2910 v
=num_mod(v
,nvalue(cadr(sc
->args
)));
2912 Error_0(sc
,"modulo: division by zero");
2914 s_return(sc
,mk_number(sc
, v
));
2916 case OP_CAR
: /* car */
2917 s_return(sc
,caar(sc
->args
));
2919 case OP_CDR
: /* cdr */
2920 s_return(sc
,cdar(sc
->args
));
2922 case OP_CONS
: /* cons */
2923 cdr(sc
->args
) = cadr(sc
->args
);
2924 s_return(sc
,sc
->args
);
2926 case OP_SETCAR
: /* set-car! */
2927 if(!is_immutable(car(sc
->args
))) {
2928 caar(sc
->args
) = cadr(sc
->args
);
2929 s_return(sc
,car(sc
->args
));
2931 Error_0(sc
,"set-car!: unable to alter immutable pair");
2934 case OP_SETCDR
: /* set-cdr! */
2935 if(!is_immutable(car(sc
->args
))) {
2936 cdar(sc
->args
) = cadr(sc
->args
);
2937 s_return(sc
,car(sc
->args
));
2939 Error_0(sc
,"set-cdr!: unable to alter immutable pair");
2942 case OP_CHAR2INT
: { /* char->integer */
2944 c
=(char)ivalue(car(sc
->args
));
2945 s_return(sc
,mk_integer(sc
,(unsigned char)c
));
2948 case OP_INT2CHAR
: { /* integer->char */
2950 c
=(unsigned char)ivalue(car(sc
->args
));
2951 s_return(sc
,mk_character(sc
,(char)c
));
2954 case OP_CHARUPCASE
: {
2956 c
=(unsigned char)ivalue(car(sc
->args
));
2958 s_return(sc
,mk_character(sc
,(char)c
));
2961 case OP_CHARDNCASE
: {
2963 c
=(unsigned char)ivalue(car(sc
->args
));
2965 s_return(sc
,mk_character(sc
,(char)c
));
2968 case OP_STR2SYM
: /* string->symbol */
2969 s_return(sc
,mk_symbol(sc
,strvalue(car(sc
->args
))));
2971 case OP_STR2ATOM
: /* string->atom */ {
2972 char *s
=strvalue(car(sc
->args
));
2974 s_return(sc
, mk_sharp_const(sc
, s
+1));
2976 s_return(sc
, mk_atom(sc
, s
));
2980 case OP_SYM2STR
: /* symbol->string */
2981 x
=mk_string(sc
,symname(car(sc
->args
)));
2984 case OP_ATOM2STR
: /* atom->string */
2986 if(is_number(x
) || is_character(x
) || is_string(x
) || is_symbol(x
)) {
2989 atom2str(sc
,x
,0,&p
,&len
);
2990 s_return(sc
,mk_counted_string(sc
,p
,len
));
2992 Error_1(sc
, "atom->string: not an atom:", x
);
2995 case OP_MKSTRING
: { /* make-string */
2999 len
=ivalue(car(sc
->args
));
3001 if(cdr(sc
->args
)!=sc
->NIL
) {
3002 fill
=charvalue(cadr(sc
->args
));
3004 s_return(sc
,mk_empty_string(sc
,len
,(char)fill
));
3007 case OP_STRLEN
: /* string-length */
3008 s_return(sc
,mk_integer(sc
,strlength(car(sc
->args
))));
3010 case OP_STRREF
: { /* string-ref */
3014 str
=strvalue(car(sc
->args
));
3016 index
=ivalue(cadr(sc
->args
));
3018 if(index
>=strlength(car(sc
->args
))) {
3019 Error_1(sc
,"string-ref: out of bounds:",cadr(sc
->args
));
3022 s_return(sc
,mk_character(sc
,((unsigned char*)str
)[index
]));
3025 case OP_STRSET
: { /* string-set! */
3030 if(is_immutable(car(sc
->args
))) {
3031 Error_1(sc
,"string-set!: unable to alter immutable string:",car(sc
->args
));
3033 str
=strvalue(car(sc
->args
));
3035 index
=ivalue(cadr(sc
->args
));
3036 if(index
>=strlength(car(sc
->args
))) {
3037 Error_1(sc
,"string-set!: out of bounds:",cadr(sc
->args
));
3040 c
=charvalue(caddr(sc
->args
));
3043 s_return(sc
,car(sc
->args
));
3046 case OP_STRAPPEND
: { /* string-append */
3047 /* in 1.29 string-append was in Scheme in init.scm but was too slow */
3052 /* compute needed length for new string */
3053 for (x
= sc
->args
; x
!= sc
->NIL
; x
= cdr(x
)) {
3054 len
+= strlength(car(x
));
3056 newstr
= mk_empty_string(sc
, len
, ' ');
3057 /* store the contents of the argument strings into the new string */
3058 for (pos
= strvalue(newstr
), x
= sc
->args
; x
!= sc
->NIL
;
3059 pos
+= strlength(car(x
)), x
= cdr(x
)) {
3060 memcpy(pos
, strvalue(car(x
)), strlength(car(x
)));
3062 s_return(sc
, newstr
);
3065 case OP_SUBSTR
: { /* substring */
3071 str
=strvalue(car(sc
->args
));
3073 index0
=ivalue(cadr(sc
->args
));
3075 if(index0
>strlength(car(sc
->args
))) {
3076 Error_1(sc
,"substring: start out of bounds:",cadr(sc
->args
));
3079 if(cddr(sc
->args
)!=sc
->NIL
) {
3080 index1
=ivalue(caddr(sc
->args
));
3081 if(index1
>strlength(car(sc
->args
)) || index1
<index0
) {
3082 Error_1(sc
,"substring: end out of bounds:",caddr(sc
->args
));
3085 index1
=strlength(car(sc
->args
));
3089 x
=mk_empty_string(sc
,len
,' ');
3090 memcpy(strvalue(x
),str
+index0
,len
);
3096 case OP_VECTOR
: { /* vector */
3099 int len
=list_length(sc
,sc
->args
);
3101 Error_1(sc
,"vector: not a proper list:",sc
->args
);
3103 vec
=mk_vector(sc
,len
);
3104 for (x
= sc
->args
, i
= 0; is_pair(x
); x
= cdr(x
), i
++) {
3105 set_vector_elem(vec
,i
,car(x
));
3110 case OP_MKVECTOR
: { /* make-vector */
3111 pointer fill
=sc
->NIL
;
3115 len
=ivalue(car(sc
->args
));
3117 if(cdr(sc
->args
)!=sc
->NIL
) {
3118 fill
=cadr(sc
->args
);
3120 vec
=mk_vector(sc
,len
);
3122 fill_vector(vec
,fill
);
3127 case OP_VECLEN
: /* vector-length */
3128 s_return(sc
,mk_integer(sc
,ivalue(car(sc
->args
))));
3130 case OP_VECREF
: { /* vector-ref */
3133 index
=ivalue(cadr(sc
->args
));
3135 if(index
>=ivalue(car(sc
->args
))) {
3136 Error_1(sc
,"vector-ref: out of bounds:",cadr(sc
->args
));
3139 s_return(sc
,vector_elem(car(sc
->args
),index
));
3142 case OP_VECSET
: { /* vector-set! */
3145 if(is_immutable(car(sc
->args
))) {
3146 Error_1(sc
,"vector-set!: unable to alter immutable vector:",car(sc
->args
));
3149 index
=ivalue(cadr(sc
->args
));
3150 if(index
>=ivalue(car(sc
->args
))) {
3151 Error_1(sc
,"vector-set!: out of bounds:",cadr(sc
->args
));
3154 set_vector_elem(car(sc
->args
),index
,caddr(sc
->args
));
3155 s_return(sc
,car(sc
->args
));
3159 sprintf(sc
->strbuff
, "%d: illegal operator", sc
->op
);
3160 Error_0(sc
,sc
->strbuff
);
3165 static int list_length(scheme
*sc
, pointer a
) {
3168 for (x
= a
, v
= 0; is_pair(x
); x
= cdr(x
)) {
3177 static pointer
opexe_3(scheme
*sc
, enum scheme_opcodes op
) {
3180 int (*comp_func
)(num
,num
)=0;
3183 case OP_NOT
: /* not */
3184 s_retbool(is_false(car(sc
->args
)));
3185 case OP_BOOLP
: /* boolean? */
3186 s_retbool(car(sc
->args
) == sc
->F
|| car(sc
->args
) == sc
->T
);
3187 case OP_EOFOBJP
: /* boolean? */
3188 s_retbool(car(sc
->args
) == sc
->EOF_OBJ
);
3189 case OP_NULLP
: /* null? */
3190 s_retbool(car(sc
->args
) == sc
->NIL
);
3191 case OP_NUMEQ
: /* = */
3192 case OP_LESS
: /* < */
3193 case OP_GRE
: /* > */
3194 case OP_LEQ
: /* <= */
3195 case OP_GEQ
: /* >= */
3197 case OP_NUMEQ
: comp_func
=num_eq
; break;
3198 case OP_LESS
: comp_func
=num_lt
; break;
3199 case OP_GRE
: comp_func
=num_gt
; break;
3200 case OP_LEQ
: comp_func
=num_le
; break;
3201 case OP_GEQ
: comp_func
=num_ge
; break;
3209 for (; x
!= sc
->NIL
; x
= cdr(x
)) {
3210 if(!comp_func(v
,nvalue(car(x
)))) {
3216 case OP_SYMBOLP
: /* symbol? */
3217 s_retbool(is_symbol(car(sc
->args
)));
3218 case OP_NUMBERP
: /* number? */
3219 s_retbool(is_number(car(sc
->args
)));
3220 case OP_STRINGP
: /* string? */
3221 s_retbool(is_string(car(sc
->args
)));
3222 case OP_INTEGERP
: /* integer? */
3223 s_retbool(is_integer(car(sc
->args
)));
3224 case OP_REALP
: /* real? */
3225 s_retbool(is_number(car(sc
->args
))); /* All numbers are real */
3226 case OP_CHARP
: /* char? */
3227 s_retbool(is_character(car(sc
->args
)));
3228 #if USE_CHAR_CLASSIFIERS
3229 case OP_CHARAP
: /* char-alphabetic? */
3230 s_retbool(Cisalpha(ivalue(car(sc
->args
))));
3231 case OP_CHARNP
: /* char-numeric? */
3232 s_retbool(Cisdigit(ivalue(car(sc
->args
))));
3233 case OP_CHARWP
: /* char-whitespace? */
3234 s_retbool(Cisspace(ivalue(car(sc
->args
))));
3235 case OP_CHARUP
: /* char-upper-case? */
3236 s_retbool(Cisupper(ivalue(car(sc
->args
))));
3237 case OP_CHARLP
: /* char-lower-case? */
3238 s_retbool(Cislower(ivalue(car(sc
->args
))));
3240 case OP_PORTP
: /* port? */
3241 s_retbool(is_port(car(sc
->args
)));
3242 case OP_INPORTP
: /* input-port? */
3243 s_retbool(is_inport(car(sc
->args
)));
3244 case OP_OUTPORTP
: /* output-port? */
3245 s_retbool(is_outport(car(sc
->args
)));
3246 case OP_PROCP
: /* procedure? */
3248 * continuation should be procedure by the example
3249 * (call-with-current-continuation procedure?) ==> #t
3250 * in R^3 report sec. 6.9
3252 s_retbool(is_proc(car(sc
->args
)) || is_closure(car(sc
->args
))
3253 || is_continuation(car(sc
->args
)) || is_foreign(car(sc
->args
)));
3254 case OP_PAIRP
: /* pair? */
3255 s_retbool(is_pair(car(sc
->args
)));
3256 case OP_LISTP
: { /* list? */
3258 slow
= fast
= car(sc
->args
);
3260 if (!is_pair(fast
)) s_retbool(fast
== sc
->NIL
);
3262 if (!is_pair(fast
)) s_retbool(fast
== sc
->NIL
);
3266 /* the fast pointer has looped back around and caught up
3267 with the slow pointer, hence the structure is circular,
3268 not of finite length, and therefore not a list */
3273 case OP_ENVP
: /* environment? */
3274 s_retbool(is_environment(car(sc
->args
)));
3275 case OP_VECTORP
: /* vector? */
3276 s_retbool(is_vector(car(sc
->args
)));
3277 case OP_EQ
: /* eq? */
3278 s_retbool(car(sc
->args
) == cadr(sc
->args
));
3279 case OP_EQV
: /* eqv? */
3280 s_retbool(eqv(car(sc
->args
), cadr(sc
->args
)));
3282 sprintf(sc
->strbuff
, "%d: illegal operator", sc
->op
);
3283 Error_0(sc
,sc
->strbuff
);
3288 static pointer
opexe_4(scheme
*sc
, enum scheme_opcodes op
) {
3292 case OP_FORCE
: /* force */
3293 sc
->code
= car(sc
->args
);
3294 if (is_promise(sc
->code
)) {
3295 /* Should change type to closure here */
3296 s_save(sc
, OP_SAVE_FORCED
, sc
->NIL
, sc
->code
);
3298 s_goto(sc
,OP_APPLY
);
3300 s_return(sc
,sc
->code
);
3303 case OP_SAVE_FORCED
: /* Save forced value replacing promise */
3304 memcpy(sc
->code
,sc
->value
,sizeof(struct cell
));
3305 s_return(sc
,sc
->value
);
3307 case OP_WRITE
: /* write */
3308 case OP_DISPLAY
: /* display */
3309 case OP_WRITE_CHAR
: /* write-char */
3310 if(is_pair(cdr(sc
->args
))) {
3311 if(cadr(sc
->args
)!=sc
->outport
) {
3312 x
=cons(sc
,sc
->outport
,sc
->NIL
);
3313 s_save(sc
,OP_SET_OUTPORT
, x
, sc
->NIL
);
3314 sc
->outport
=cadr(sc
->args
);
3317 sc
->args
= car(sc
->args
);
3323 s_goto(sc
,OP_P0LIST
);
3325 case OP_NEWLINE
: /* newline */
3326 if(is_pair(sc
->args
)) {
3327 if(car(sc
->args
)!=sc
->outport
) {
3328 x
=cons(sc
,sc
->outport
,sc
->NIL
);
3329 s_save(sc
,OP_SET_OUTPORT
, x
, sc
->NIL
);
3330 sc
->outport
=car(sc
->args
);
3336 case OP_ERR0
: /* error */
3338 if (!is_string(car(sc
->args
))) {
3339 sc
->args
=cons(sc
,mk_string(sc
," -- "),sc
->args
);
3340 setimmutable(car(sc
->args
));
3342 putstr(sc
, "Error: ");
3343 putstr(sc
, strvalue(car(sc
->args
)));
3344 sc
->args
= cdr(sc
->args
);
3347 case OP_ERR1
: /* error */
3349 if (sc
->args
!= sc
->NIL
) {
3350 s_save(sc
,OP_ERR1
, cdr(sc
->args
), sc
->NIL
);
3351 sc
->args
= car(sc
->args
);
3353 s_goto(sc
,OP_P0LIST
);
3356 if(sc
->interactive_repl
) {
3357 s_goto(sc
,OP_T0LVL
);
3363 case OP_REVERSE
: /* reverse */
3364 s_return(sc
,reverse(sc
, car(sc
->args
)));
3366 case OP_LIST_STAR
: /* list* */
3367 s_return(sc
,list_star(sc
,sc
->args
));
3369 case OP_APPEND
: /* append */
3370 if(sc
->args
==sc
->NIL
) {
3371 s_return(sc
,sc
->NIL
);
3374 if(cdr(sc
->args
)==sc
->NIL
) {
3375 s_return(sc
,sc
->args
);
3377 for (y
= cdr(sc
->args
); y
!= sc
->NIL
; y
= cdr(y
)) {
3378 x
=append(sc
,x
,car(y
));
3383 case OP_PUT
: /* put */
3384 if (!hasprop(car(sc
->args
)) || !hasprop(cadr(sc
->args
))) {
3385 Error_0(sc
,"illegal use of put");
3387 for (x
= symprop(car(sc
->args
)), y
= cadr(sc
->args
); x
!= sc
->NIL
; x
= cdr(x
)) {
3393 cdar(x
) = caddr(sc
->args
);
3395 symprop(car(sc
->args
)) = cons(sc
, cons(sc
, y
, caddr(sc
->args
)),
3396 symprop(car(sc
->args
)));
3399 case OP_GET
: /* get */
3400 if (!hasprop(car(sc
->args
)) || !hasprop(cadr(sc
->args
))) {
3401 Error_0(sc
,"illegal use of get");
3403 for (x
= symprop(car(sc
->args
)), y
= cadr(sc
->args
); x
!= sc
->NIL
; x
= cdr(x
)) {
3409 s_return(sc
,cdar(x
));
3411 s_return(sc
,sc
->NIL
);
3413 #endif /* USE_PLIST */
3414 case OP_QUIT
: /* quit */
3415 if(is_pair(sc
->args
)) {
3416 sc
->retcode
=ivalue(car(sc
->args
));
3420 case OP_GC
: /* gc */
3421 gc(sc
, sc
->NIL
, sc
->NIL
);
3424 case OP_GCVERB
: /* gc-verbose */
3425 { int was
= sc
->gc_verbose
;
3427 sc
->gc_verbose
= (car(sc
->args
) != sc
->F
);
3431 case OP_NEWSEGMENT
: /* new-segment */
3432 if (!is_pair(sc
->args
) || !is_number(car(sc
->args
))) {
3433 Error_0(sc
,"new-segment: argument must be a number");
3435 alloc_cellseg(sc
, (int) ivalue(car(sc
->args
)));
3438 case OP_OBLIST
: /* oblist */
3439 s_return(sc
, oblist_all_symbols(sc
));
3441 case OP_CURR_INPORT
: /* current-input-port */
3442 s_return(sc
,sc
->inport
);
3444 case OP_CURR_OUTPORT
: /* current-output-port */
3445 s_return(sc
,sc
->outport
);
3447 case OP_OPEN_INFILE
: /* open-input-file */
3448 case OP_OPEN_OUTFILE
: /* open-output-file */
3449 case OP_OPEN_INOUTFILE
: /* open-input-output-file */ {
3453 case OP_OPEN_INFILE
: prop
=port_input
; break;
3454 case OP_OPEN_OUTFILE
: prop
=port_output
; break;
3455 case OP_OPEN_INOUTFILE
: prop
=port_input
|port_output
; break;
3459 p
=port_from_filename(sc
,strvalue(car(sc
->args
)),prop
);
3466 #if USE_STRING_PORTS
3467 case OP_OPEN_INSTRING
: /* open-input-string */
3468 case OP_OPEN_OUTSTRING
: /* open-output-string */
3469 case OP_OPEN_INOUTSTRING
: /* open-input-output-string */ {
3473 case OP_OPEN_INSTRING
: prop
=port_input
; break;
3474 case OP_OPEN_OUTSTRING
: prop
=port_output
; break;
3475 case OP_OPEN_INOUTSTRING
: prop
=port_input
|port_output
; break;
3479 p
=port_from_string(sc
, strvalue(car(sc
->args
)),
3480 strvalue(car(sc
->args
))+strlength(car(sc
->args
)), prop
);
3488 case OP_CLOSE_INPORT
: /* close-input-port */
3489 port_close(sc
,car(sc
->args
),port_input
);
3492 case OP_CLOSE_OUTPORT
: /* close-output-port */
3493 port_close(sc
,car(sc
->args
),port_output
);
3496 case OP_INT_ENV
: /* interaction-environment */
3497 s_return(sc
,sc
->global_env
);
3499 case OP_CURR_ENV
: /* current-environment */
3500 s_return(sc
,sc
->envir
);
3507 static pointer
opexe_5(scheme
*sc
, enum scheme_opcodes op
) {
3510 if(sc
->nesting
!=0) {
3514 Error_1(sc
,"unmatched parentheses:",mk_integer(sc
,n
));
3518 /* ========== reading part ========== */
3520 if(!is_pair(sc
->args
)) {
3521 s_goto(sc
,OP_READ_INTERNAL
);
3523 if(!is_inport(car(sc
->args
))) {
3524 Error_1(sc
,"read: not an input port:",car(sc
->args
));
3526 if(car(sc
->args
)==sc
->inport
) {
3527 s_goto(sc
,OP_READ_INTERNAL
);
3530 sc
->inport
=car(sc
->args
);
3531 x
=cons(sc
,x
,sc
->NIL
);
3532 s_save(sc
,OP_SET_INPORT
, x
, sc
->NIL
);
3533 s_goto(sc
,OP_READ_INTERNAL
);
3535 case OP_READ_CHAR
: /* read-char */
3536 case OP_PEEK_CHAR
: /* peek-char */ {
3538 if(is_pair(sc
->args
)) {
3539 if(car(sc
->args
)!=sc
->inport
) {
3541 x
=cons(sc
,x
,sc
->NIL
);
3542 s_save(sc
,OP_SET_INPORT
, x
, sc
->NIL
);
3543 sc
->inport
=car(sc
->args
);
3548 s_return(sc
,sc
->EOF_OBJ
);
3550 if(sc
->op
==OP_PEEK_CHAR
) {
3553 s_return(sc
,mk_character(sc
,c
));
3556 case OP_CHAR_READY
: /* char-ready? */ {
3557 pointer p
=sc
->inport
;
3559 if(is_pair(sc
->args
)) {
3562 res
=p
->_object
._port
->kind
&port_string
;
3566 case OP_SET_INPORT
: /* set-input-port */
3567 sc
->inport
=car(sc
->args
);
3568 s_return(sc
,sc
->value
);
3570 case OP_SET_OUTPORT
: /* set-output-port */
3571 sc
->outport
=car(sc
->args
);
3572 s_return(sc
,sc
->value
);
3577 if(sc
->inport
==sc
->loadport
) {
3581 s_return(sc
,sc
->EOF_OBJ
);
3585 while ((c
=inchar(sc
)) != '\n' && c
!=EOF
)
3587 sc
->tok
= token(sc
);
3588 s_goto(sc
,OP_RDSEXPR
);
3591 s_save(sc
,OP_RDVEC
,sc
->NIL
,sc
->NIL
);
3594 sc
->tok
= token(sc
);
3595 if (sc
->tok
== TOK_RPAREN
) {
3596 s_return(sc
,sc
->NIL
);
3597 } else if (sc
->tok
== TOK_DOT
) {
3598 Error_0(sc
,"syntax error: illegal dot expression");
3600 sc
->nesting_stack
[sc
->file_i
]++;
3601 s_save(sc
,OP_RDLIST
, sc
->NIL
, sc
->NIL
);
3602 s_goto(sc
,OP_RDSEXPR
);
3605 s_save(sc
,OP_RDQUOTE
, sc
->NIL
, sc
->NIL
);
3606 sc
->tok
= token(sc
);
3607 s_goto(sc
,OP_RDSEXPR
);
3609 sc
->tok
= token(sc
);
3610 if(sc
->tok
==TOK_VEC
) {
3611 s_save(sc
,OP_RDQQUOTEVEC
, sc
->NIL
, sc
->NIL
);
3613 s_goto(sc
,OP_RDSEXPR
);
3615 s_save(sc
,OP_RDQQUOTE
, sc
->NIL
, sc
->NIL
);
3617 s_goto(sc
,OP_RDSEXPR
);
3619 s_save(sc
,OP_RDUNQUOTE
, sc
->NIL
, sc
->NIL
);
3620 sc
->tok
= token(sc
);
3621 s_goto(sc
,OP_RDSEXPR
);
3623 s_save(sc
,OP_RDUQTSP
, sc
->NIL
, sc
->NIL
);
3624 sc
->tok
= token(sc
);
3625 s_goto(sc
,OP_RDSEXPR
);
3627 s_return(sc
,mk_atom(sc
, readstr_upto(sc
, "();\t\n\r ")));
3631 Error_0(sc
,"Error reading string");
3636 pointer f
=find_slot_in_env(sc
,sc
->envir
,sc
->SHARP_HOOK
,1);
3638 Error_0(sc
,"undefined sharp expression");
3640 sc
->code
=cons(sc
,slot_value_in_env(f
),sc
->NIL
);
3644 case TOK_SHARP_CONST
:
3645 if ((x
= mk_sharp_const(sc
, readstr_upto(sc
, "();\t\n\r "))) == sc
->NIL
) {
3646 Error_0(sc
,"undefined sharp expression");
3651 Error_0(sc
,"syntax error: illegal token");
3656 sc
->args
= cons(sc
, sc
->value
, sc
->args
);
3657 sc
->tok
= token(sc
);
3658 if (sc
->tok
== TOK_COMMENT
) {
3660 while ((c
=inchar(sc
)) != '\n' && c
!=EOF
)
3662 sc
->tok
= token(sc
);
3664 if (sc
->tok
== TOK_RPAREN
) {
3666 if (c
!= '\n') backchar(sc
,c
);
3667 sc
->nesting_stack
[sc
->file_i
]--;
3668 s_return(sc
,reverse_in_place(sc
, sc
->NIL
, sc
->args
));
3669 } else if (sc
->tok
== TOK_DOT
) {
3670 s_save(sc
,OP_RDDOT
, sc
->args
, sc
->NIL
);
3671 sc
->tok
= token(sc
);
3672 s_goto(sc
,OP_RDSEXPR
);
3674 s_save(sc
,OP_RDLIST
, sc
->args
, sc
->NIL
);;
3675 s_goto(sc
,OP_RDSEXPR
);
3680 if (token(sc
) != TOK_RPAREN
) {
3681 Error_0(sc
,"syntax error: illegal dot expression");
3683 sc
->nesting_stack
[sc
->file_i
]--;
3684 s_return(sc
,reverse_in_place(sc
, sc
->value
, sc
->args
));
3688 s_return(sc
,cons(sc
, sc
->QUOTE
, cons(sc
, sc
->value
, sc
->NIL
)));
3691 s_return(sc
,cons(sc
, sc
->QQUOTE
, cons(sc
, sc
->value
, sc
->NIL
)));
3693 case OP_RDQQUOTEVEC
:
3694 s_return(sc
,cons(sc
, mk_symbol(sc
,"apply"),
3695 cons(sc
, mk_symbol(sc
,"vector"),
3696 cons(sc
,cons(sc
, sc
->QQUOTE
,
3697 cons(sc
,sc
->value
,sc
->NIL
)),
3701 s_return(sc
,cons(sc
, sc
->UNQUOTE
, cons(sc
, sc
->value
, sc
->NIL
)));
3704 s_return(sc
,cons(sc
, sc
->UNQUOTESP
, cons(sc
, sc
->value
, sc
->NIL
)));
3707 /*sc->code=cons(sc,mk_proc(sc,OP_VECTOR),sc->value);
3708 s_goto(sc,OP_EVAL); Cannot be quoted*/
3709 /*x=cons(sc,mk_proc(sc,OP_VECTOR),sc->value);
3710 s_return(sc,x); Cannot be part of pairs*/
3711 /*sc->code=mk_proc(sc,OP_VECTOR);
3713 s_goto(sc,OP_APPLY);*/
3715 s_goto(sc
,OP_VECTOR
);
3717 /* ========== printing part ========== */
3719 if(is_vector(sc
->args
)) {
3721 sc
->args
=cons(sc
,sc
->args
,mk_integer(sc
,0));
3722 s_goto(sc
,OP_PVECFROM
);
3723 } else if(is_environment(sc
->args
)) {
3724 putstr(sc
,"#<ENVIRONMENT>");
3726 } else if (!is_pair(sc
->args
)) {
3727 printatom(sc
, sc
->args
, sc
->print_flag
);
3729 } else if (car(sc
->args
) == sc
->QUOTE
&& ok_abbrev(cdr(sc
->args
))) {
3731 sc
->args
= cadr(sc
->args
);
3732 s_goto(sc
,OP_P0LIST
);
3733 } else if (car(sc
->args
) == sc
->QQUOTE
&& ok_abbrev(cdr(sc
->args
))) {
3735 sc
->args
= cadr(sc
->args
);
3736 s_goto(sc
,OP_P0LIST
);
3737 } else if (car(sc
->args
) == sc
->UNQUOTE
&& ok_abbrev(cdr(sc
->args
))) {
3739 sc
->args
= cadr(sc
->args
);
3740 s_goto(sc
,OP_P0LIST
);
3741 } else if (car(sc
->args
) == sc
->UNQUOTESP
&& ok_abbrev(cdr(sc
->args
))) {
3743 sc
->args
= cadr(sc
->args
);
3744 s_goto(sc
,OP_P0LIST
);
3747 s_save(sc
,OP_P1LIST
, cdr(sc
->args
), sc
->NIL
);
3748 sc
->args
= car(sc
->args
);
3749 s_goto(sc
,OP_P0LIST
);
3753 if (is_pair(sc
->args
)) {
3754 s_save(sc
,OP_P1LIST
, cdr(sc
->args
), sc
->NIL
);
3756 sc
->args
= car(sc
->args
);
3757 s_goto(sc
,OP_P0LIST
);
3758 } else if(is_vector(sc
->args
)) {
3759 s_save(sc
,OP_P1LIST
,sc
->NIL
,sc
->NIL
);
3761 s_goto(sc
,OP_P0LIST
);
3763 if (sc
->args
!= sc
->NIL
) {
3765 printatom(sc
, sc
->args
, sc
->print_flag
);
3771 int i
=ivalue_unchecked(cdr(sc
->args
));
3772 pointer vec
=car(sc
->args
);
3773 int len
=ivalue_unchecked(vec
);
3778 pointer elem
=vector_elem(vec
,i
);
3779 ivalue_unchecked(cdr(sc
->args
))=i
+1;
3780 s_save(sc
,OP_PVECFROM
, sc
->args
, sc
->NIL
);
3783 s_goto(sc
,OP_P0LIST
);
3788 sprintf(sc
->strbuff
, "%d: illegal operator", sc
->op
);
3789 Error_0(sc
,sc
->strbuff
);
3795 static pointer
opexe_6(scheme
*sc
, enum scheme_opcodes op
) {
3800 case OP_LIST_LENGTH
: /* length */ /* a.k */
3801 v
=list_length(sc
,car(sc
->args
));
3803 Error_1(sc
,"length: not a list:",car(sc
->args
));
3805 s_return(sc
,mk_integer(sc
, v
));
3807 case OP_ASSQ
: /* assq */ /* a.k */
3809 for (y
= cadr(sc
->args
); is_pair(y
); y
= cdr(y
)) {
3810 if (!is_pair(car(y
))) {
3811 Error_0(sc
,"unable to handle non pair element");
3817 s_return(sc
,car(y
));
3823 case OP_GET_CLOSURE
: /* get-closure-code */ /* a.k */
3824 sc
->args
= car(sc
->args
);
3825 if (sc
->args
== sc
->NIL
) {
3827 } else if (is_closure(sc
->args
)) {
3828 s_return(sc
,cons(sc
, sc
->LAMBDA
, closure_code(sc
->value
)));
3829 } else if (is_macro(sc
->args
)) {
3830 s_return(sc
,cons(sc
, sc
->LAMBDA
, closure_code(sc
->value
)));
3834 case OP_CLOSUREP
: /* closure? */
3836 * Note, macro object is also a closure.
3837 * Therefore, (closure? <#MACRO>) ==> #t
3839 s_retbool(is_closure(car(sc
->args
)));
3840 case OP_MACROP
: /* macro? */
3841 s_retbool(is_macro(car(sc
->args
)));
3843 sprintf(sc
->strbuff
, "%d: illegal operator", sc
->op
);
3844 Error_0(sc
,sc
->strbuff
);
3846 return sc
->T
; /* NOTREACHED */
3849 typedef pointer (*dispatch_func
)(scheme
*, enum scheme_opcodes
);
3851 typedef int (*test_predicate
)(pointer
);
3852 static int is_any(pointer p
) { return 1;}
3853 static int is_num_integer(pointer p
) {
3854 return is_number(p
) && ((p
)->_object
._number
.is_fixnum
);
3856 static int is_nonneg(pointer p
) {
3857 return is_num_integer(p
) && ivalue(p
)>=0;
3860 /* Correspond carefully with following defines! */
3867 {is_string
, "string"},
3868 {is_symbol
, "symbol"},
3872 {is_environment
, "environment"},
3875 {is_character
, "character"},
3876 {is_vector
, "vector"},
3877 {is_number
, "number"},
3878 {is_num_integer
, "integer"},
3879 {is_nonneg
, "non-negative integer"}
3883 #define TST_ANY "\001"
3884 #define TST_STRING "\002"
3885 #define TST_SYMBOL "\003"
3886 #define TST_PORT "\004"
3887 #define TST_INPORT "\005"
3888 #define TST_OUTPORT "\006"
3889 #define TST_ENVIRONMENT "\007"
3890 #define TST_PAIR "\010"
3891 #define TST_LIST "\011"
3892 #define TST_CHAR "\012"
3893 #define TST_VECTOR "\013"
3894 #define TST_NUMBER "\014"
3895 #define TST_INTEGER "\015"
3896 #define TST_NATURAL "\016"
3903 char *arg_tests_encoding
;
3906 #define INF_ARG 0xffff
3908 static op_code_info dispatch_table
[]= {
3909 #define _OP_DEF(A,B,C,D,E,OP) {A,B,C,D,E},
3910 #include "opdefines.h"
3914 static const char *procname(pointer x
) {
3916 const char *name
=dispatch_table
[n
].name
;
3923 /* kernel of this interpreter */
3924 static void Eval_Cycle(scheme
*sc
, enum scheme_opcodes op
) {
3930 op_code_info
*pcd
=dispatch_table
+sc
->op
;
3931 if (pcd
->name
!=0) { /* if built-in function, check arguments */
3934 int n
=list_length(sc
,sc
->args
);
3936 /* Check number of arguments */
3937 if(n
<pcd
->min_arity
) {
3939 sprintf(msg
,"%s: needs%s %d argument(s)",
3941 pcd
->min_arity
==pcd
->max_arity
?"":" at least",
3944 if(ok
&& n
>pcd
->max_arity
) {
3946 sprintf(msg
,"%s: needs%s %d argument(s)",
3948 pcd
->min_arity
==pcd
->max_arity
?"":" at most",
3952 if(pcd
->arg_tests_encoding
!=0) {
3955 const char *t
=pcd
->arg_tests_encoding
;
3956 pointer arglist
=sc
->args
;
3958 pointer arg
=car(arglist
);
3960 if(j
==TST_INPORT
[0]) {
3961 if(!is_inport(arg
)) break;
3962 } else if(j
==TST_OUTPORT
[0]) {
3963 if(!is_outport(arg
)) break;
3964 } else if(j
==TST_LIST
[0]) {
3965 if(arg
!=sc
->NIL
&& !is_pair(arg
)) break;
3967 if(!tests
[j
].fct(arg
)) break;
3970 if(t
[1]!=0) {/* last test is replicated as necessary */
3973 arglist
=cdr(arglist
);
3978 sprintf(msg
,"%s: argument %d must be: %s",
3986 if(_Error_1(sc
,msg
,0)==sc
->NIL
) {
3989 pcd
=dispatch_table
+sc
->op
;
3993 if (pcd
->func(sc
, (enum scheme_opcodes
)sc
->op
) == sc
->NIL
) {
3997 fprintf(stderr
,"No memory!\n");
4004 /* ========== Initialization of internal keywords ========== */
4006 static void assign_syntax(scheme
*sc
, char *name
) {
4009 x
= oblist_add_by_name(sc
, name
);
4010 typeflag(x
) |= T_SYNTAX
;
4013 static void assign_proc(scheme
*sc
, enum scheme_opcodes op
, char *name
) {
4016 x
= mk_symbol(sc
, name
);
4018 new_slot_in_env(sc
, x
, y
);
4021 static pointer
mk_proc(scheme
*sc
, enum scheme_opcodes op
) {
4024 y
= get_cell(sc
, sc
->NIL
, sc
->NIL
);
4025 typeflag(y
) = (T_PROC
| T_ATOM
);
4026 ivalue_unchecked(y
) = (long) op
;
4031 /* Hard-coded for the given keywords. Remember to rewrite if more are added! */
4032 static int syntaxnum(pointer p
) {
4033 const char *s
=strvalue(car(p
));
4034 switch(strlength(car(p
))) {
4036 if(s
[0]=='i') return OP_IF0
; /* if */
4037 else return OP_OR0
; /* or */
4039 if(s
[0]=='a') return OP_AND0
; /* and */
4040 else return OP_LET0
; /* let */
4043 case 'e': return OP_CASE0
; /* case */
4044 case 'd': return OP_COND0
; /* cond */
4045 case '*': return OP_LET0AST
; /* let* */
4046 default: return OP_SET0
; /* set! */
4050 case 'g': return OP_BEGIN
; /* begin */
4051 case 'l': return OP_DELAY
; /* delay */
4052 case 'c': return OP_MACRO0
; /* macro */
4053 default: return OP_QUOTE
; /* quote */
4057 case 'm': return OP_LAMBDA
; /* lambda */
4058 case 'f': return OP_DEF0
; /* define */
4059 default: return OP_LET0REC
; /* letrec */
4062 return OP_C0STREAM
; /* cons-stream */
4066 /* initialization of TinyScheme */
4068 INTERFACE
static pointer
s_cons(scheme
*sc
, pointer a
, pointer b
) {
4069 return cons(sc
,a
,b
);
4071 INTERFACE
static pointer
s_immutable_cons(scheme
*sc
, pointer a
, pointer b
) {
4072 return immutable_cons(sc
,a
,b
);
4075 static struct scheme_interface vtbl
={
4136 scheme
*scheme_init_new() {
4137 scheme
*sc
=(scheme
*)malloc(sizeof(scheme
));
4138 if(!scheme_init(sc
)) {
4146 scheme
*scheme_init_new_custom_alloc(func_alloc malloc
, func_dealloc free
) {
4147 scheme
*sc
=(scheme
*)malloc(sizeof(scheme
));
4148 if(!scheme_init_custom_alloc(sc
,malloc
,free
)) {
4157 int scheme_init(scheme
*sc
) {
4158 return scheme_init_custom_alloc(sc
,malloc
,free
);
4161 int scheme_init_custom_alloc(scheme
*sc
, func_alloc malloc
, func_dealloc free
) {
4162 int i
, n
=sizeof(dispatch_table
)/sizeof(dispatch_table
[0]);
4165 num_zero
.is_fixnum
=1;
4166 num_zero
.value
.ivalue
=0;
4167 num_one
.is_fixnum
=1;
4168 num_one
.value
.ivalue
=1;
4176 sc
->last_cell_seg
= -1;
4177 sc
->sink
= &sc
->_sink
;
4178 sc
->NIL
= &sc
->_NIL
;
4179 sc
->T
= &sc
->_HASHT
;
4180 sc
->F
= &sc
->_HASHF
;
4181 sc
->EOF_OBJ
=&sc
->_EOF_OBJ
;
4182 sc
->free_cell
= &sc
->_NIL
;
4186 sc
->outport
=sc
->NIL
;
4187 sc
->save_inport
=sc
->NIL
;
4188 sc
->loadport
=sc
->NIL
;
4190 sc
->interactive_repl
=0;
4192 if (alloc_cellseg(sc
,FIRST_CELLSEGS
) != FIRST_CELLSEGS
) {
4197 dump_stack_initialize(sc
);
4202 typeflag(sc
->NIL
) = (T_ATOM
| MARK
);
4203 car(sc
->NIL
) = cdr(sc
->NIL
) = sc
->NIL
;
4205 typeflag(sc
->T
) = (T_ATOM
| MARK
);
4206 car(sc
->T
) = cdr(sc
->T
) = sc
->T
;
4208 typeflag(sc
->F
) = (T_ATOM
| MARK
);
4209 car(sc
->F
) = cdr(sc
->F
) = sc
->F
;
4210 sc
->oblist
= oblist_initial_value(sc
);
4211 /* init global_env */
4212 new_frame_in_env(sc
, sc
->NIL
);
4213 sc
->global_env
= sc
->envir
;
4215 x
= mk_symbol(sc
,"else");
4216 new_slot_in_env(sc
, x
, sc
->T
);
4218 assign_syntax(sc
, "lambda");
4219 assign_syntax(sc
, "quote");
4220 assign_syntax(sc
, "define");
4221 assign_syntax(sc
, "if");
4222 assign_syntax(sc
, "begin");
4223 assign_syntax(sc
, "set!");
4224 assign_syntax(sc
, "let");
4225 assign_syntax(sc
, "let*");
4226 assign_syntax(sc
, "letrec");
4227 assign_syntax(sc
, "cond");
4228 assign_syntax(sc
, "delay");
4229 assign_syntax(sc
, "and");
4230 assign_syntax(sc
, "or");
4231 assign_syntax(sc
, "cons-stream");
4232 assign_syntax(sc
, "macro");
4233 assign_syntax(sc
, "case");
4235 for(i
=0; i
<n
; i
++) {
4236 if(dispatch_table
[i
].name
!=0) {
4237 assign_proc(sc
, (enum scheme_opcodes
)i
, dispatch_table
[i
].name
);
4241 /* initialization of global pointers to special symbols */
4242 sc
->LAMBDA
= mk_symbol(sc
, "lambda");
4243 sc
->QUOTE
= mk_symbol(sc
, "quote");
4244 sc
->QQUOTE
= mk_symbol(sc
, "quasiquote");
4245 sc
->UNQUOTE
= mk_symbol(sc
, "unquote");
4246 sc
->UNQUOTESP
= mk_symbol(sc
, "unquote-splicing");
4247 sc
->FEED_TO
= mk_symbol(sc
, "=>");
4248 sc
->COLON_HOOK
= mk_symbol(sc
,"*colon-hook*");
4249 sc
->ERROR_HOOK
= mk_symbol(sc
, "*error-hook*");
4250 sc
->SHARP_HOOK
= mk_symbol(sc
, "*sharp-hook*");
4252 return !sc
->no_memory
;
4255 void scheme_set_input_port_file(scheme
*sc
, FILE *fin
) {
4256 sc
->inport
=port_from_file(sc
,fin
,port_input
);
4259 void scheme_set_input_port_string(scheme
*sc
, char *start
, char *past_the_end
) {
4260 sc
->inport
=port_from_string(sc
,start
,past_the_end
,port_input
);
4263 void scheme_set_output_port_file(scheme
*sc
, FILE *fout
) {
4264 sc
->outport
=port_from_file(sc
,fout
,port_output
);
4267 void scheme_set_output_port_string(scheme
*sc
, char *start
, char *past_the_end
) {
4268 sc
->outport
=port_from_string(sc
,start
,past_the_end
,port_output
);
4271 void scheme_set_external_data(scheme
*sc
, void *p
) {
4275 void scheme_deinit(scheme
*sc
) {
4279 sc
->global_env
=sc
->NIL
;
4280 dump_stack_free(sc
);
4285 if(is_port(sc
->inport
)) {
4286 typeflag(sc
->inport
) = T_ATOM
;
4289 sc
->outport
=sc
->NIL
;
4290 if(is_port(sc
->save_inport
)) {
4291 typeflag(sc
->save_inport
) = T_ATOM
;
4293 sc
->save_inport
=sc
->NIL
;
4294 if(is_port(sc
->loadport
)) {
4295 typeflag(sc
->loadport
) = T_ATOM
;
4297 sc
->loadport
=sc
->NIL
;
4299 gc(sc
,sc
->NIL
,sc
->NIL
);
4301 for(i
=0; i
<=sc
->last_cell_seg
; i
++) {
4302 sc
->free(sc
->alloc_seg
[i
]);
4306 void scheme_load_file(scheme
*sc
, FILE *fin
) {
4307 dump_stack_reset(sc
);
4308 sc
->envir
= sc
->global_env
;
4310 sc
->load_stack
[0].kind
=port_input
|port_file
;
4311 sc
->load_stack
[0].rep
.stdio
.file
=fin
;
4312 sc
->loadport
=mk_port(sc
,sc
->load_stack
);
4315 sc
->interactive_repl
=1;
4317 sc
->inport
=sc
->loadport
;
4318 Eval_Cycle(sc
, OP_T0LVL
);
4319 typeflag(sc
->loadport
)=T_ATOM
;
4320 if(sc
->retcode
==0) {
4321 sc
->retcode
=sc
->nesting
!=0;
4325 void scheme_load_string(scheme
*sc
, const char *cmd
) {
4326 dump_stack_reset(sc
);
4327 sc
->envir
= sc
->global_env
;
4329 sc
->load_stack
[0].kind
=port_input
|port_string
;
4330 sc
->load_stack
[0].rep
.string
.start
=(char*)cmd
; /* This func respects const */
4331 sc
->load_stack
[0].rep
.string
.past_the_end
=(char*)cmd
+strlen(cmd
);
4332 sc
->load_stack
[0].rep
.string
.curr
=(char*)cmd
;
4333 sc
->loadport
=mk_port(sc
,sc
->load_stack
);
4335 sc
->interactive_repl
=0;
4336 sc
->inport
=sc
->loadport
;
4337 Eval_Cycle(sc
, OP_T0LVL
);
4338 typeflag(sc
->loadport
)=T_ATOM
;
4339 if(sc
->retcode
==0) {
4340 sc
->retcode
=sc
->nesting
!=0;
4344 void scheme_define(scheme
*sc
, pointer envir
, pointer symbol
, pointer value
) {
4347 x
=find_slot_in_env(sc
,envir
,symbol
,0);
4349 set_slot_in_env(sc
, x
, value
);
4351 new_slot_spec_in_env(sc
, envir
, symbol
, value
);
4356 void scheme_apply0(scheme
*sc
, const char *procname
) {
4357 pointer carx
=mk_symbol(sc
,procname
);
4358 pointer cdrx
=sc
->NIL
;
4360 dump_stack_reset(sc
);
4361 sc
->envir
= sc
->global_env
;
4362 sc
->code
= cons(sc
,carx
,cdrx
);
4363 sc
->interactive_repl
=0;
4365 Eval_Cycle(sc
,OP_EVAL
);
4368 void scheme_call(scheme
*sc
, pointer func
, pointer args
) {
4369 dump_stack_reset(sc
);
4370 sc
->envir
= sc
->global_env
;
4373 sc
->interactive_repl
=0;
4375 Eval_Cycle(sc
, OP_APPLY
);
4379 /* ========== Main ========== */
4386 extern MacTS_main(int argc
, char **argv
);
4388 int argc
= ccommand(&argv
);
4389 MacTS_main(argc
,argv
);
4392 int MacTS_main(int argc
, char **argv
) {
4394 int main(int argc
, char **argv
) {
4398 char *file_name
=InitFile
;
4405 if(argc
==2 && strcmp(argv
[1],"-?")==0) {
4406 printf("Usage: %s [-? | <file1> <file2> ... | -1 <file> <arg1> <arg2> ...]\n\tUse - as filename for stdin.\n",argv
[0]);
4409 if(!scheme_init(&sc
)) {
4410 fprintf(stderr
,"Could not initialize!\n");
4413 scheme_set_input_port_file(&sc
, stdin
);
4414 scheme_set_output_port_file(&sc
, stdout
);
4416 scheme_define(&sc
,sc
.global_env
,mk_symbol(&sc
,"load-extension"),mk_foreign_func(&sc
, scm_load_ext
));
4419 if(access(file_name
,0)!=0) {
4420 char *p
=getenv("TINYSCHEMEINIT");
4426 if(strcmp(file_name
,"-")==0) {
4428 } else if(strcmp(file_name
,"-1")==0 || strcmp(file_name
,"-c")==0) {
4429 pointer args
=sc
.NIL
;
4430 isfile
=file_name
[1]=='1';
4432 if(strcmp(file_name
,"-")==0) {
4435 fin
=fopen(file_name
,"r");
4437 for(;*argv
;argv
++) {
4438 pointer value
=mk_string(&sc
,*argv
);
4439 args
=cons(&sc
,value
,args
);
4441 args
=reverse_in_place(&sc
,sc
.NIL
,args
);
4442 scheme_define(&sc
,sc
.global_env
,mk_symbol(&sc
,"*args*"),args
);
4445 fin
=fopen(file_name
,"r");
4447 if(isfile
&& fin
==0) {
4448 fprintf(stderr
,"Could not open file %s\n",file_name
);
4451 scheme_load_file(&sc
,fin
);
4453 scheme_load_string(&sc
,file_name
);
4455 if(!isfile
|| fin
!=stdin
) {
4457 fprintf(stderr
,"Errors encountered reading %s\n",file_name
);
4465 } while(file_name
!=0);
4467 scheme_load_file(&sc
,stdin
);