4 void box_boolean(bool value)
10 bool unbox_boolean(void)
15 /* the array is full of undefined data, and must be correctly filled before the
16 next GC. size is in cells */
17 F_ARRAY *allot_array(CELL type, F_FIXNUM capacity)
22 general_error(ERROR_NEGATIVE_ARRAY_SIZE,tag_integer(capacity),F,true);
24 array = allot_object(type,array_size(capacity));
25 array->capacity = tag_fixnum(capacity);
29 /* make a new array with an initial element */
30 F_ARRAY *array(CELL type, F_FIXNUM capacity, CELL fill)
33 F_ARRAY* array = allot_array(type, capacity);
34 for(i = 0; i < capacity; i++)
35 put(AREF(array,i),fill);
39 /* size is in bytes this time */
40 F_ARRAY *byte_array(F_FIXNUM size)
42 F_FIXNUM byte_size = (size + sizeof(CELL) - 1) / sizeof(CELL);
43 return array(BYTE_ARRAY_TYPE,byte_size,0);
46 /* push a new array on the stack */
47 void primitive_array(void)
53 size = to_fixnum(dpop());
54 dpush(tag_object(array(ARRAY_TYPE,size,initial)));
57 /* push a new tuple on the stack */
58 void primitive_tuple(void)
64 size = to_fixnum(dpop());
66 tuple = array(TUPLE_TYPE,size,F);
67 put(AREF(tuple,0),class);
68 dpush(tag_object(tuple));
71 /* push a new byte on the stack */
72 void primitive_byte_array(void)
74 F_FIXNUM size = to_fixnum(dpop());
76 dpush(tag_object(byte_array(size)));
79 /* push a new quotation on the stack */
80 void primitive_quotation(void)
84 size = to_fixnum(dpop());
85 dpush(tag_object(array(QUOTATION_TYPE,size,F)));
88 CELL make_array_2(CELL v1, CELL v2)
90 F_ARRAY *a = array(ARRAY_TYPE,2,F);
96 CELL make_array_4(CELL v1, CELL v2, CELL v3, CELL v4)
98 F_ARRAY *a = array(ARRAY_TYPE,4,F);
103 return tag_object(a);
106 F_ARRAY* resize_array(F_ARRAY* array, F_FIXNUM capacity, CELL fill)
111 CELL to_copy = array_capacity(array);
112 if(capacity < to_copy)
115 new_array = allot_array(untag_header(array->header),capacity);
117 memcpy(new_array + 1,array + 1,to_copy * CELLS);
119 for(i = to_copy; i < capacity; i++)
120 put(AREF(new_array,i),fill);
125 void primitive_resize_array(void)
128 F_FIXNUM capacity = to_fixnum(dpeek2());
129 maybe_gc(array_size(capacity));
130 array = untag_array(dpop());
131 drepl(tag_object(resize_array(array,capacity,F)));
134 void primitive_array_to_tuple(void)
136 CELL array = dpeek();
137 type_check(ARRAY_TYPE,array);
138 array = clone(array);
139 put(SLOT(UNTAG(array),0),tag_header(TUPLE_TYPE));
143 void primitive_tuple_to_array(void)
145 CELL tuple = dpeek();
146 type_check(TUPLE_TYPE,tuple);
147 tuple = clone(tuple);
148 put(SLOT(UNTAG(tuple),0),tag_header(ARRAY_TYPE));
152 F_VECTOR* vector(F_FIXNUM capacity)
154 F_VECTOR* vector = allot_object(VECTOR_TYPE,sizeof(F_VECTOR));
155 vector->top = tag_fixnum(0);
156 vector->array = tag_object(array(ARRAY_TYPE,capacity,F));
160 void primitive_vector(void)
162 CELL size = to_fixnum(dpeek());
163 maybe_gc(array_size(size) + sizeof(F_VECTOR));
164 drepl(tag_object(vector(size)));
167 void primitive_array_to_vector(void)
171 maybe_gc(sizeof(F_VECTOR));
172 array = untag_array(dpeek());
173 vector = allot_object(VECTOR_TYPE,sizeof(F_VECTOR));
174 vector->top = array->capacity;
175 vector->array = tag_object(array);
176 drepl(tag_object(vector));
180 F_STRING* allot_string(F_FIXNUM capacity)
185 general_error(ERROR_NEGATIVE_ARRAY_SIZE,tag_integer(capacity),F,true);
187 string = allot_object(STRING_TYPE,
188 sizeof(F_STRING) + (capacity + 1) * CHARS);
189 /* strings are null-terminated in memory, even though they also
190 have a length field. The null termination allows us to add
191 the sizeof(F_STRING) to a Factor string to get a C-style
192 UTF16 string for C library calls. */
193 cput(SREF(string,capacity),(u16)'\0');
194 string->length = tag_fixnum(capacity);
195 string->hashcode = F;
199 /* call this after constructing a string */
200 void rehash_string(F_STRING* str)
204 CELL capacity = string_capacity(str);
205 for(i = 0; i < capacity; i++)
206 hash = (31*hash + string_nth(str,i));
207 str->hashcode = (s32)tag_fixnum(hash);
210 void primitive_rehash_string(void)
212 rehash_string(untag_string(dpop()));
216 F_STRING *string(F_FIXNUM capacity, CELL fill)
220 F_STRING* string = allot_string(capacity);
222 for(i = 0; i < capacity; i++)
223 cput(SREF(string,i),fill);
225 rehash_string(string);
230 void primitive_string(void)
232 CELL initial = to_cell(dpop());
233 F_FIXNUM length = to_fixnum(dpop());
234 maybe_gc(string_size(length));
235 dpush(tag_object(string(length,initial)));
238 F_STRING* resize_string(F_STRING* string, F_FIXNUM capacity, u16 fill)
240 /* later on, do an optimization: if end of array is here, just grow */
242 CELL to_copy = string_capacity(string);
244 if(capacity < to_copy)
247 F_STRING* new_string = allot_string(capacity);
249 memcpy(new_string + 1,string + 1,to_copy * CHARS);
251 for(i = to_copy; i < capacity; i++)
252 cput(SREF(new_string,i),fill);
257 void primitive_resize_string(void)
260 CELL capacity = to_fixnum(dpeek2());
261 maybe_gc(string_size(capacity));
262 string = untag_string_fast(dpop());
263 drepl(tag_object(resize_string(string,capacity,0)));
266 /* Some ugly macros to prevent a 2x code duplication */
268 #define MEMORY_TO_STRING(type,utype) \
269 F_STRING *memory_to_##type##_string(const type *string, CELL length) \
271 F_STRING* s = allot_string(length); \
273 for(i = 0; i < length; i++) \
275 cput(SREF(s,i),(utype)*string); \
281 void primitive_memory_to_##type##_string(void) \
283 CELL length = unbox_unsigned_cell(); \
284 type *string = (type*)unbox_unsigned_cell(); \
285 dpush(tag_object(memory_to_##type##_string(string,length))); \
287 F_STRING *from_##type##_string(const type *str) \
291 while(*scan++) length++; \
292 return memory_to_##type##_string((type*)str,length); \
294 void box_##type##_string(const type *str) \
296 dpush(str ? tag_object(from_##type##_string(str)) : F); \
298 void primitive_alien_to_##type##_string(void) \
301 drepl(tag_object(from_##type##_string(alien_offset(dpeek())))); \
304 MEMORY_TO_STRING(char,u8)
305 MEMORY_TO_STRING(u16,u16)
307 void check_string(F_STRING *s, CELL max)
309 CELL capacity = string_capacity(s);
311 for(i = 0; i < capacity; i++)
313 u16 ch = string_nth(s,i);
314 if(ch == '\0' || ch >= (1 << (max * 8)))
315 general_error(ERROR_C_STRING,tag_object(s),F,true);
319 F_ARRAY *allot_c_string(CELL capacity, CELL size)
321 return allot_array(BYTE_ARRAY_TYPE,capacity * size / CELLS + 1);
324 #define STRING_TO_MEMORY(type) \
325 void type##_string_to_memory(F_STRING *s, type *string) \
328 CELL capacity = string_capacity(s); \
329 for(i = 0; i < capacity; i++) \
330 string[i] = string_nth(s,i); \
332 void primitive_##type##_string_to_memory(void) \
334 type *address = (type*)unbox_unsigned_cell(); \
335 F_STRING *str = untag_string(dpop()); \
336 type##_string_to_memory(str,address); \
338 F_ARRAY *string_to_##type##_alien(F_STRING *s, bool check) \
340 CELL capacity = string_capacity(s); \
342 if(check) check_string(s,sizeof(type)); \
343 _c_str = allot_c_string(capacity,sizeof(type)); \
344 type *c_str = (type*)(_c_str + 1); \
345 type##_string_to_memory(s,c_str); \
346 c_str[capacity] = 0; \
349 type *to_##type##_string(F_STRING *s, bool check) \
351 if(sizeof(type) == sizeof(u16)) \
353 if(check) check_string(s,sizeof(type)); \
354 return (type*)(s + 1); \
357 return (type*)(string_to_##type##_alien(s,check) + 1); \
359 type *unbox_##type##_string(void) \
361 return to_##type##_string(untag_string(dpop()),true); \
363 void primitive_string_to_##type##_alien(void) \
368 t = type_of(string); \
369 if(t != ALIEN_TYPE && t != BYTE_ARRAY_TYPE && t != F_TYPE) \
370 drepl(tag_object(string_to_##type##_alien(untag_string(string),true))); \
373 STRING_TO_MEMORY(char);
374 STRING_TO_MEMORY(u16);
376 void primitive_char_slot(void)
378 F_STRING* string = untag_string_fast(dpop());
379 CELL index = untag_fixnum_fast(dpop());
380 dpush(tag_fixnum(string_nth(string,index)));
383 void primitive_set_char_slot(void)
385 F_STRING* string = untag_string_fast(dpop());
386 CELL index = untag_fixnum_fast(dpop());
387 CELL value = untag_fixnum_fast(dpop());
388 set_string_nth(string,index,value);
391 F_SBUF* sbuf(F_FIXNUM capacity)
395 general_error(ERROR_NEGATIVE_ARRAY_SIZE,tag_integer(capacity),F,true);
396 sbuf = allot_object(SBUF_TYPE,sizeof(F_SBUF));
397 sbuf->top = tag_fixnum(0);
398 sbuf->string = tag_object(string(capacity,'\0'));
402 void primitive_sbuf(void)
404 CELL size = to_fixnum(dpeek());
405 maybe_gc(sizeof(F_SBUF) + string_size(size));
406 drepl(tag_object(sbuf(size)));
409 void primitive_hashtable(void)
413 hash = allot_object(HASHTABLE_TYPE,sizeof(F_HASHTABLE));
417 dpush(tag_object(hash));
420 void update_xt(F_WORD* word)
423 word->xt = primitive_to_xt(to_fixnum(word->primitive));
426 /* <word> ( name vocabulary -- word ) */
427 void primitive_word(void)
430 CELL name, vocabulary;
432 maybe_gc(sizeof(F_WORD));
436 word = allot_object(WORD_TYPE,sizeof(F_WORD));
437 word->hashcode = tag_fixnum(rand());
439 word->vocabulary = vocabulary;
440 word->primitive = tag_fixnum(0);
444 word->xt = (CELL)undefined;
445 dpush(tag_word(word));
448 void primitive_update_xt(void)
450 update_xt(untag_word(dpop()));
453 void primitive_word_xt(void)
455 F_WORD *word = untag_word(dpeek());
456 drepl(tag_cell(word->xt));
459 void fixup_word(F_WORD* word)
461 /* If this is a compiled word, relocate the code pointer. Otherwise,
462 reset it based on the primitive number of the word. */
463 if(word->compiledp != F)
464 code_fixup(&word->xt);
469 void primitive_wrapper(void)
473 maybe_gc(sizeof(F_WRAPPER));
475 wrapper = allot_object(WRAPPER_TYPE,sizeof(F_WRAPPER));
476 wrapper->object = dpeek();
477 drepl(tag_wrapper(wrapper));