1 /* <Built-in procedures> */
3 /* Creates a closure and adds it to the top-level
4 @param name (string) the name of the built-in procedure
5 @param code (void*) the address of the built-in procedure (label address)
7 #define CREATE_BUILTIN_CLOS(name,code) \
8 r_res = (int)getSymbol((name),topLevel); /* create a hash bucket */ \
9 ((SymbolEntry*)r_res)->sob = makeSchemeClosure(NULL,(code)); \
10 ASSERT_ALWAYS( ((SymbolEntry*)r_res)->sob!=NULL,"" ); \
11 ((SymbolEntry*)r_res)->isDefined = 1;
13 /* The stack when in a built-in precedure (there is no fp):
15 | ret | - return address
16 | env | - points to the enviroment vector
17 | n | - number of arguments
21 | An-1 | - argument n-1
23 Macros for built-in procedures:
25 #define BI_ST_ARG(n) (stack[sp-4-(n)])
26 #define BI_ST_ARG_COUNT() (stack[sp-3])
27 #define BI_ST_RET() (stack[sp-1])
28 #define BI_RETURN() goto *pop()
30 goto Lstart
; /* skip all definitions */
33 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("car",1) );
35 ASSERT_ALWAYS( IS_SOB_PAIR(r
[0]), MSG_ERR_NOTPAIR
);
36 r_res
= (int)SOB_PAIR_CAR(r
[0]);
40 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("cdr",1) );
42 ASSERT_ALWAYS( IS_SOB_PAIR(r
[0]), MSG_ERR_NOTPAIR
);
43 r_res
= (int)SOB_PAIR_CDR(r
[0]);
47 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("symbol?",1) );
49 if ( IS_SOB_SYMBOL(r
[0]) ) goto Lsymbol_true
;
50 r_res
= (int)&sc_false
;
53 r_res
= (int)&sc_true
;
57 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==2,MSG_ERR_ARGCOUNT("set-car!",2) );
60 ASSERT_ALWAYS( IS_SOB_PAIR(r
[0]), MSG_ERR_NOTPAIR
);
61 SOB_PAIR_CAR(r
[0]) = (SchemeObject
*)r
[1];
62 r_res
= (int)&sc_void
;
66 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==2,MSG_ERR_ARGCOUNT("set-cdr!",2) );
69 ASSERT_ALWAYS( IS_SOB_PAIR(r
[0]), MSG_ERR_NOTPAIR
);
70 SOB_PAIR_CDR(r
[0]) = (SchemeObject
*)r
[1];
71 r_res
= (int)&sc_void
;
75 ASSERT_ALWAYS( BI_ST_ARG_COUNT()>=1,MSG_ERR_ARGCOUNT("make-vector",1) );
77 ASSERT_ALWAYS(IS_SOB_INT((SchemeObject
*)r
[0]), "");
78 r
[0] = SOB_INT_VALUE(r
[0]);
79 r_res
= (int)makeSchemeVectorInit(r
[0],&sc_void
);
80 /* initialize vector elements */
83 for (r
[1]=0; r
[1]<r
[0]; ++r
[1]) {
84 if (r
[1]+1<BI_ST_ARG_COUNT()) r
[2]=BI_ST_ARG(r
[1]+1);
85 SOB_VECTOR_SET(r_res
,r
[1],(void*)r
[2]);
90 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==3,MSG_ERR_ARGCOUNT("vector-set!",3) );
92 ASSERT_ALWAYS(IS_SOB_VECTOR((SchemeObject
*)r
[0]), "");
94 ASSERT_ALWAYS(IS_SOB_INT((SchemeObject
*)r
[1]), "");
95 r
[1] = SOB_INT_VALUE((SchemeObject
*)r
[1]);
97 SOB_VECTOR_SET((SchemeObject
*)r
[0],r
[1],(SchemeObject
*)r
[2]);
98 r_res
= (int)&sc_void
;
102 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==2,MSG_ERR_ARGCOUNT("vector-ref",2) );
104 ASSERT_ALWAYS(IS_SOB_VECTOR((SchemeObject
*)r
[0]), "");
106 ASSERT_ALWAYS(IS_SOB_INT((SchemeObject
*)r
[1]), "");
107 r
[1] = SOB_INT_VALUE((SchemeObject
*)r
[1]);
108 r_res
= (int)SOB_VECTOR_REF((SchemeObject
*)r
[0],r
[1]);
112 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("vector-length",1) );
114 ASSERT_ALWAYS( IS_SOB_VECTOR(r
[0]), "" );
115 r_res
= SOB_VECTOR_LENGTH(r
[0]);
116 r_res
= (int)makeSchemeInt(r_res
);
120 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==2,MSG_ERR_ARGCOUNT("binary=?",2) );
122 ASSERT_ALWAYS(IS_SOB_INT((SchemeObject
*)r
[0]), "");
123 r
[0] = SOB_INT_VALUE((SchemeObject
*)r
[0]);
125 ASSERT_ALWAYS(IS_SOB_INT((SchemeObject
*)r
[1]), "");
126 r
[1] = SOB_INT_VALUE((SchemeObject
*)r
[1]);
127 if (r
[0] != r
[1]) goto LbinaryEQ_false
;
128 r_res
= (int)&sc_true
;
131 r_res
= (int)&sc_false
;
135 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==2,MSG_ERR_ARGCOUNT("binary-add",2) );
137 ASSERT_ALWAYS(IS_SOB_INT((SchemeObject
*)r
[0]), "");
138 r
[0] = SOB_INT_VALUE((SchemeObject
*)r
[0]);
140 ASSERT_ALWAYS(IS_SOB_INT((SchemeObject
*)r
[1]), "");
141 r
[1] = SOB_INT_VALUE((SchemeObject
*)r
[1]);
143 r_res
= (int)makeSchemeInt( r_res
);
147 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==2,MSG_ERR_ARGCOUNT("binary-sub",2) );
149 ASSERT_ALWAYS(IS_SOB_INT((SchemeObject
*)r
[0]), "");
150 r
[0] = SOB_INT_VALUE((SchemeObject
*)r
[0]);
152 ASSERT_ALWAYS(IS_SOB_INT((SchemeObject
*)r
[1]), "");
153 r
[1] = SOB_INT_VALUE((SchemeObject
*)r
[1]);
155 r_res
= (int)makeSchemeInt( r_res
);
159 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==2,MSG_ERR_ARGCOUNT("binary-mul",2) );
161 ASSERT_ALWAYS(IS_SOB_INT((SchemeObject
*)r
[0]), "");
162 r
[0] = SOB_INT_VALUE((SchemeObject
*)r
[0]);
164 ASSERT_ALWAYS(IS_SOB_INT((SchemeObject
*)r
[1]), "");
165 r
[1] = SOB_INT_VALUE((SchemeObject
*)r
[1]);
166 r_res
= (int)r
[0] * (int)r
[1]; /* multiply as signed integers */
167 r_res
= (int)makeSchemeInt( r_res
);
171 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==2,MSG_ERR_ARGCOUNT("binary-div",2) );
173 ASSERT_ALWAYS(IS_SOB_INT((SchemeObject
*)r
[0]), "");
174 r
[0] = SOB_INT_VALUE((SchemeObject
*)r
[0]);
176 ASSERT_ALWAYS(IS_SOB_INT((SchemeObject
*)r
[1]), "");
177 r
[1] = SOB_INT_VALUE((SchemeObject
*)r
[1]);
178 ASSERT_ALWAYS( (int)r
[1]!=0, MSG_ERR_DIVZERO
);
179 r_res
= (int)r
[0] / (int)r
[1]; /* divide as signed integers */
180 r_res
= (int)makeSchemeInt( r_res
);
184 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==2,MSG_ERR_ARGCOUNT("binary<?",2) );
186 ASSERT_ALWAYS(IS_SOB_INT((SchemeObject
*)r
[0]), "");
187 r
[0] = SOB_INT_VALUE((SchemeObject
*)r
[0]);
189 ASSERT_ALWAYS(IS_SOB_INT((SchemeObject
*)r
[1]), "");
190 r
[1] = SOB_INT_VALUE((SchemeObject
*)r
[1]);
191 r_res
= ((int)r
[0] < (int)r
[1]); /* compare as signed integers */
192 if ( r_res
) goto LbinaryLT_true
;
193 r_res
= (int)&sc_false
;
196 r_res
= (int)&sc_true
;
200 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("box",1) );
202 r_res
= (int)makeSchemeVectorInit( 1,(SchemeObject
*)(r
[0]) );
206 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("null?",1) );
208 if ( IS_SOB_NIL(r
[0]) ) goto Lnull_true
;
209 r_res
= (int)&sc_false
;
212 r_res
= (int)&sc_true
;
216 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("char->integer",1) );
218 ASSERT_ALWAYS( IS_SOB_CHAR(r
[0]), "" );
219 r
[0] = (unsigned char)SOB_CHAR_VALUE(r
[0]);
220 r_res
= (int)makeSchemeInt( (int)r
[0] );
224 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("integer->char",1) );
226 ASSERT_ALWAYS( IS_SOB_INT(r
[0]), "" );
227 r
[0] = SOB_INT_VALUE(r
[0]);
228 r_res
= (int)makeSchemeChar( (char)r
[0] );
234 ASSERT_ALWAYS( ST_ARG_COUNT()==2,MSG_ERR_ARGCOUNT("apply",2) );
235 r
[0] = ST_ARG(0); /* r[0] is now the closure */
236 ASSERT_ALWAYS( IS_SOB_CLOSURE(r
[0]), MSG_ERR_APPNONPROC
);
237 r
[1] = ST_ARG(1); /* r[1] is now the list of arguments */
238 ASSERT_ALWAYS( (r
[1]==(int)&sc_nil
) | (IS_SOB_PAIR(r
[1])), MSG_ERR_NOTLIST
);
239 /* push arguments (backwards) and number of arguments */
240 pushArgsList( (SchemeObject
*)r
[1] );
241 /* push env. of closure */
242 push( (int)SOB_CLOSURE_ENV(r
[0]) );
243 /* push current return address (it's a tail call) */
244 push( (int)ST_RET() );
245 /* override current frame (it's a tail call) */
248 goto *SOB_CLOSURE_CODE(r
[0]);
251 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("boolean?",1) );
253 r_res
= (IS_SOB_BOOL(r
[0])) ? (int)&sc_true
: (int)&sc_false
;
257 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("char?",1) );
259 r_res
= (IS_SOB_CHAR(r
[0])) ? (int)&sc_true
: (int)&sc_false
;
263 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("integer?",1) );
265 r_res
= (IS_SOB_INT(r
[0])) ? (int)&sc_true
: (int)&sc_false
;
269 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("pair?",1) );
271 r_res
= (IS_SOB_PAIR(r
[0])) ? (int)&sc_true
: (int)&sc_false
;
275 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("procedure?",1) );
277 r_res
= (IS_SOB_CLOSURE(r
[0])) ? (int)&sc_true
: (int)&sc_false
;
281 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("string?",1) );
283 r_res
= (IS_SOB_STRING(r
[0])) ? (int)&sc_true
: (int)&sc_false
;
287 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("vector?",1) );
289 r_res
= (IS_SOB_VECTOR(r
[0])) ? (int)&sc_true
: (int)&sc_false
;
293 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("zero?",1) );
295 ASSERT_ALWAYS( IS_SOB_INT(r
[0]), "" );
296 r
[0] = SOB_INT_VALUE(r
[0]);
297 r_res
= (r
[0]==0) ? (int)&sc_true
: (int)&sc_false
;
301 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==2,MSG_ERR_ARGCOUNT("cons",2) );
304 r_res
= (int)makeSchemePair( (SchemeObject
*)r
[0], (SchemeObject
*)r
[1] );
308 /* The eq? procedure compare the
313 and the ADDRESSES of pairs,
317 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==2,MSG_ERR_ARGCOUNT("eq?",2) );
320 if ( IS_SOB_BOOL(r
[0]) ) goto Leq_boolval
;
321 if ( IS_SOB_CHAR(r
[0]) ) goto Leq_charval
;
322 if ( IS_SOB_INT(r
[0]) ) goto Leq_intval
;
323 if ( IS_SOB_SYMBOL(r
[0]) ) goto Leq_symval
;
324 if ( r
[0]==r
[1] ) goto Leq_true
;
327 if ( !IS_SOB_BOOL(r
[1]) ) goto Leq_false
;
328 if ( SOB_BOOL_VALUE(r
[0])==SOB_BOOL_VALUE(r
[1]) ) goto Leq_true
;
331 if ( !IS_SOB_CHAR(r
[1]) ) goto Leq_false
;
332 if ( SOB_CHAR_VALUE(r
[0])==SOB_CHAR_VALUE(r
[1]) ) goto Leq_true
;
335 if ( !IS_SOB_INT(r
[1]) ) goto Leq_false
;
336 if ( SOB_INT_VALUE(r
[0])==SOB_INT_VALUE(r
[1]) ) goto Leq_true
;
339 if ( !IS_SOB_SYMBOL(r
[1]) ) goto Leq_false
;
340 if ( SOB_SYMBOL_ENTRY(r
[0])==SOB_SYMBOL_ENTRY(r
[1]) ) goto Leq_true
;
343 r_res
= (int)&sc_true
;
346 r_res
= (int)&sc_false
;
350 ASSERT_ALWAYS( BI_ST_ARG_COUNT()>=1,MSG_ERR_ARGCOUNT("make-string",1) );
352 ASSERT_ALWAYS(IS_SOB_INT((SchemeObject
*)r
[0]), "");
353 r
[0] = SOB_INT_VALUE(r
[0]);
355 if (BI_ST_ARG_COUNT()==1) goto Lmake_string_make
;
357 ASSERT_ALWAYS(IS_SOB_CHAR((SchemeObject
*)r
[1]), "");
358 r
[1] = (int)SOB_CHAR_VALUE(r
[1]);
360 r_res
= (int)makeSchemeString(r
[0],(char)r
[1]);
364 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==2,MSG_ERR_ARGCOUNT("remainder",2) );
366 ASSERT_ALWAYS( IS_SOB_INT(r
[0]), "" );
367 r
[0] = SOB_INT_VALUE(r
[0]);
369 ASSERT_ALWAYS( IS_SOB_INT(r
[1]), "" );
370 r
[1] = SOB_INT_VALUE(r
[1]);
371 ASSERT_ALWAYS( (int)r
[1]!=0, MSG_ERR_DIVZERO
);
372 r_res
= (int)r
[0] % (int)r
[1]; /* divide as signed integers */
373 r_res
= (int)makeSchemeInt( r_res
);
377 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("string->symbol",1) );
379 ASSERT_ALWAYS( IS_SOB_STRING(r
[0]), "" );
380 r
[0] = (int)SOB_STRING_VALUE(r
[0]);
381 r_res
= (int)makeSchemeSymbol((char*)r
[0]);
385 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("symbol->string",1) );
387 ASSERT_ALWAYS( IS_SOB_SYMBOL(r
[0]), "" );
388 r
[0] = (int)SOB_SYMBOL_NAME(r
[0]);
389 r_res
= (int)makeSchemeStringFromCString( (char*)r
[0] );
393 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==1,MSG_ERR_ARGCOUNT("string-length",1) );
395 ASSERT_ALWAYS( IS_SOB_STRING(r
[0]), "" );
396 r_res
= SOB_STRING_LENGTH(r
[0]);
397 r_res
= (int)makeSchemeInt(r_res
);
401 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==2,MSG_ERR_ARGCOUNT("string-ref",2) );
403 ASSERT_ALWAYS( IS_SOB_STRING(r
[0]), "" );
405 ASSERT_ALWAYS( IS_SOB_INT(r
[1]), "" );
406 r
[1] = SOB_INT_VALUE( r
[1] );
407 ASSERT_ALWAYS( (r
[1]>=0) & (r
[1]<SOB_STRING_LENGTH(r
[0])), MSG_ERR_NDXOUTOFBOUNDS
);
408 r_res
= SOB_STRING_REF(r
[0],r
[1]);
409 r_res
= (int)makeSchemeChar(r_res
);
413 ASSERT_ALWAYS( BI_ST_ARG_COUNT()==3,MSG_ERR_ARGCOUNT("string-set!",3) );
415 ASSERT_ALWAYS( IS_SOB_STRING(r
[0]), "" );
418 ASSERT_ALWAYS( IS_SOB_INT(r
[1]), "" );
419 r
[1] = SOB_INT_VALUE( r
[1] );
420 ASSERT_ALWAYS( (r
[1]>=0) & (r
[1]<SOB_STRING_LENGTH(r
[0])), MSG_ERR_NDXOUTOFBOUNDS
);
423 ASSERT_ALWAYS( IS_SOB_CHAR(r
[2]), "" );
424 r
[2] = SOB_CHAR_VALUE( r
[2] );
425 SOB_STRING_SET((SchemeObject
*)r
[0],r
[1],(char)r
[2]);
426 r_res
= (int)&sc_void
;
430 /* create closures for the free variables of the built-in procedures */
431 CREATE_BUILTIN_CLOS("car" ,&&Lcar
);
432 CREATE_BUILTIN_CLOS("cdr" ,&&Lcdr
);
433 CREATE_BUILTIN_CLOS("symbol?" ,&&Lsymbol
);
434 CREATE_BUILTIN_CLOS("set-car!" ,&&Lset_car
);
435 CREATE_BUILTIN_CLOS("set-cdr!" ,&&Lset_cdr
);
436 CREATE_BUILTIN_CLOS("make-vector" ,&&Lmake_vector
);
437 CREATE_BUILTIN_CLOS("vector-set!" ,&&Lvector_set
);
438 CREATE_BUILTIN_CLOS("vector-ref" ,&&Lvector_ref
);
439 CREATE_BUILTIN_CLOS("vector-length" ,&&Lvector_length
);
440 CREATE_BUILTIN_CLOS("binary=?" ,&&LbinaryEQ
);
441 CREATE_BUILTIN_CLOS("binary-add" ,&&LbinaryADD
);
442 CREATE_BUILTIN_CLOS("binary-sub" ,&&LbinarySUB
);
443 CREATE_BUILTIN_CLOS("binary-mul" ,&&LbinaryMUL
);
444 CREATE_BUILTIN_CLOS("binary-div" ,&&LbinaryDIV
);
445 CREATE_BUILTIN_CLOS("binary<?" ,&&LbinaryLT
);
446 CREATE_BUILTIN_CLOS("box" ,&&Lbox
);
447 CREATE_BUILTIN_CLOS("null?" ,&&Lnull
);
448 CREATE_BUILTIN_CLOS("char->integer" ,&&Lchar_to_integer
);
449 CREATE_BUILTIN_CLOS("integer->char" ,&&Linteger_to_char
);
450 CREATE_BUILTIN_CLOS("apply" ,&&Lapply
);
451 CREATE_BUILTIN_CLOS("boolean?" ,&&Lboolean
);
452 CREATE_BUILTIN_CLOS("char?" ,&&Lchar
);
453 CREATE_BUILTIN_CLOS("cons" ,&&Lcons
);
454 CREATE_BUILTIN_CLOS("eq?" ,&&Leq
);
455 CREATE_BUILTIN_CLOS("integer?" ,&&Linteger
);
456 CREATE_BUILTIN_CLOS("make-string" ,&&Lmake_string
);
457 CREATE_BUILTIN_CLOS("number?" ,&&Linteger
); /* same as integer? */
458 CREATE_BUILTIN_CLOS("pair?" ,&&Lpair
);
459 CREATE_BUILTIN_CLOS("procedure?" ,&&Lprocedure
);
460 CREATE_BUILTIN_CLOS("string?" ,&&Lstring
);
461 CREATE_BUILTIN_CLOS("vector?" ,&&Lvector
);
462 CREATE_BUILTIN_CLOS("zero?" ,&&Lzero
);
463 CREATE_BUILTIN_CLOS("remainder" ,&&Lremainder
);
464 CREATE_BUILTIN_CLOS("string->symbol",&&Lstring_to_symbol
);
465 CREATE_BUILTIN_CLOS("symbol->string",&&Lsymbol_to_string
);
466 CREATE_BUILTIN_CLOS("string-length" ,&&Lstring_length
);
467 CREATE_BUILTIN_CLOS("string-ref" ,&&Lstring_ref
);
468 CREATE_BUILTIN_CLOS("string-set!" ,&&Lstring_set
);
470 /* </Built-in procedures> */