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_internal(CELL type, F_FIXNUM capacity)
23 simple_error(ERROR_NEGATIVE_ARRAY_SIZE,allot_integer(capacity),F);
28 array = allot_object(type,array_size(capacity));
29 array->capacity = tag_fixnum(capacity);
34 /* make a new array with an initial element */
35 F_ARRAY *allot_array(CELL type, F_FIXNUM capacity, CELL fill)
39 F_ARRAY* array = allot_array_internal(type, capacity);
40 UNREGISTER_ROOT(fill);
41 for(i = 0; i < capacity; i++)
42 set_array_nth(array,i,fill);
46 /* size is in bytes this time */
47 F_ARRAY *allot_byte_array(F_FIXNUM size)
51 simple_error(ERROR_NEGATIVE_ARRAY_SIZE,allot_integer(size),F);
55 CELL byte_size = (size + sizeof(CELL) - 1) / sizeof(CELL);
56 return allot_array(BYTE_ARRAY_TYPE,byte_size,0);
59 /* push a new array on the stack */
60 void primitive_array(void)
62 CELL initial = dpop();
63 F_FIXNUM size = unbox_signed_cell();
64 dpush(tag_object(allot_array(ARRAY_TYPE,size,initial)));
67 /* push a new byte on the stack */
68 void primitive_byte_array(void)
70 F_FIXNUM size = unbox_signed_cell();
71 dpush(tag_object(allot_byte_array(size)));
74 CELL allot_array_4(CELL v1, CELL v2, CELL v3, CELL v4)
80 F_ARRAY *a = allot_array_internal(ARRAY_TYPE,4);
85 set_array_nth(a,0,v1);
86 set_array_nth(a,1,v2);
87 set_array_nth(a,2,v3);
88 set_array_nth(a,3,v4);
92 F_ARRAY *reallot_array(F_ARRAY* array, F_FIXNUM capacity, CELL fill)
97 CELL to_copy = array_capacity(array);
98 if(capacity < to_copy)
101 REGISTER_ARRAY(array);
104 new_array = allot_array_internal(untag_header(array->header),capacity);
106 UNREGISTER_ROOT(fill);
107 UNREGISTER_ARRAY(array);
109 memcpy(new_array + 1,array + 1,to_copy * CELLS);
111 for(i = to_copy; i < capacity; i++)
112 set_array_nth(new_array,i,fill);
117 void primitive_resize_array(void)
119 F_ARRAY* array = untag_array(dpop());
120 F_FIXNUM capacity = unbox_signed_cell();
121 dpush(tag_object(reallot_array(array,capacity,F)));
124 void primitive_become(void)
126 CELL type = unbox_signed_cell();
128 put(SLOT(UNTAG(obj),0),tag_header(type));
131 void primitive_array_to_vector(void)
133 F_VECTOR *vector = allot_object(VECTOR_TYPE,sizeof(F_VECTOR));
134 F_ARRAY *array = untag_array(dpeek());
135 vector->top = array->capacity;
136 vector->array = tag_object(array);
137 drepl(tag_object(vector));
141 F_STRING* allot_string_internal(F_FIXNUM capacity)
147 simple_error(ERROR_NEGATIVE_ARRAY_SIZE,allot_integer(capacity),F);
152 string = allot_object(STRING_TYPE,
153 sizeof(F_STRING) + (capacity + 1) * CHARS);
154 /* strings are null-terminated in memory, even though they also
155 have a length field. The null termination allows us to add
156 the sizeof(F_STRING) to a Factor string to get a C-style
157 UTF16 string for C library calls. */
158 cput(SREF(string,capacity),(u16)'\0');
159 string->length = tag_fixnum(capacity);
160 string->hashcode = F;
165 /* call this after constructing a string */
166 void rehash_string(F_STRING* str)
170 CELL capacity = string_capacity(str);
171 for(i = 0; i < capacity; i++)
172 hash = (31*hash + string_nth(str,i));
173 str->hashcode = (s32)tag_fixnum(hash);
176 void primitive_rehash_string(void)
178 rehash_string(untag_string(dpop()));
182 F_STRING *allot_string(F_FIXNUM capacity, CELL fill)
186 F_STRING* string = allot_string_internal(capacity);
188 for(i = 0; i < capacity; i++)
189 cput(SREF(string,i),fill);
191 rehash_string(string);
196 void primitive_string(void)
198 CELL initial = unbox_unsigned_cell();
199 F_FIXNUM length = unbox_signed_cell();
200 dpush(tag_object(allot_string(length,initial)));
203 F_STRING* reallot_string(F_STRING* string, F_FIXNUM capacity, u16 fill)
205 /* later on, do an optimization: if end of array is here, just grow */
207 CELL to_copy = string_capacity(string);
209 if(capacity < to_copy)
212 REGISTER_STRING(string);
214 F_STRING *new_string = allot_string_internal(capacity);
216 UNREGISTER_STRING(string);
218 memcpy(new_string + 1,string + 1,to_copy * CHARS);
220 for(i = to_copy; i < capacity; i++)
221 cput(SREF(new_string,i),fill);
226 void primitive_resize_string(void)
228 F_STRING* string = untag_string(dpop());
229 F_FIXNUM capacity = unbox_signed_cell();
230 dpush(tag_object(reallot_string(string,capacity,0)));
233 /* Some ugly macros to prevent a 2x code duplication */
235 #define MEMORY_TO_STRING(type,utype) \
236 F_STRING *memory_to_##type##_string(const type *string, CELL length) \
238 REGISTER_C_STRING(string); \
239 F_STRING* s = allot_string_internal(length); \
240 UNREGISTER_C_STRING(string); \
242 for(i = 0; i < length; i++) \
244 cput(SREF(s,i),(utype)*string); \
250 void primitive_memory_to_##type##_string(void) \
252 CELL length = unbox_unsigned_cell(); \
253 const type *string = (const type*)unbox_unsigned_cell(); \
254 dpush(tag_object(memory_to_##type##_string(string,length))); \
256 F_STRING *from_##type##_string(const type *str) \
259 const type *scan = str; \
260 while(*scan++) length++; \
261 return memory_to_##type##_string(str,length); \
263 void box_##type##_string(const type *str) \
265 dpush(str ? tag_object(from_##type##_string(str)) : F); \
267 void primitive_alien_to_##type##_string(void) \
269 drepl(tag_object(from_##type##_string(alien_offset(dpeek())))); \
272 MEMORY_TO_STRING(char,u8)
273 MEMORY_TO_STRING(u16,u16)
275 bool check_string(F_STRING *s, CELL max)
277 CELL capacity = string_capacity(s);
279 for(i = 0; i < capacity; i++)
281 u16 ch = string_nth(s,i);
282 if(ch == '\0' || ch >= (1 << (max * 8)))
288 F_ARRAY *allot_c_string(CELL capacity, CELL size)
290 return allot_array_internal(BYTE_ARRAY_TYPE,capacity * size / CELLS + 1);
293 #define STRING_TO_MEMORY(type) \
294 void type##_string_to_memory(F_STRING *s, type *string) \
297 CELL capacity = string_capacity(s); \
298 for(i = 0; i < capacity; i++) \
299 string[i] = string_nth(s,i); \
301 void primitive_##type##_string_to_memory(void) \
303 type *address = (type*)unbox_unsigned_cell(); \
304 F_STRING *str = untag_string(dpop()); \
305 type##_string_to_memory(str,address); \
307 F_ARRAY *string_to_##type##_alien(F_STRING *s, bool check) \
309 CELL capacity = string_capacity(s); \
311 if(check && !check_string(s,sizeof(type))) \
312 simple_error(ERROR_C_STRING,tag_object(s),F); \
313 REGISTER_STRING(s); \
314 _c_str = allot_c_string(capacity,sizeof(type)); \
315 UNREGISTER_STRING(s); \
316 type *c_str = (type*)(_c_str + 1); \
317 type##_string_to_memory(s,c_str); \
318 c_str[capacity] = 0; \
321 type *to_##type##_string(F_STRING *s, bool check) \
323 if(sizeof(type) == sizeof(u16)) \
325 if(check && !check_string(s,sizeof(type))) \
326 simple_error(ERROR_C_STRING,tag_object(s),F); \
327 return (type*)(s + 1); \
330 return (type*)(string_to_##type##_alien(s,check) + 1); \
332 type *unbox_##type##_string(void) \
334 return to_##type##_string(untag_string(dpop()),true); \
336 void primitive_string_to_##type##_alien(void) \
340 t = type_of(string); \
341 if(t != ALIEN_TYPE && t != BYTE_ARRAY_TYPE && t != F_TYPE) \
342 drepl(tag_object(string_to_##type##_alien(untag_string(string),true))); \
345 STRING_TO_MEMORY(char);
346 STRING_TO_MEMORY(u16);
348 void primitive_char_slot(void)
350 F_STRING* string = untag_string_fast(dpop());
351 CELL index = untag_fixnum_fast(dpop());
352 dpush(tag_fixnum(string_nth(string,index)));
355 void primitive_set_char_slot(void)
357 F_STRING* string = untag_string_fast(dpop());
358 CELL index = untag_fixnum_fast(dpop());
359 CELL value = untag_fixnum_fast(dpop());
360 set_string_nth(string,index,value);
363 void primitive_string_to_sbuf(void)
365 F_SBUF *sbuf = allot_object(SBUF_TYPE,sizeof(F_SBUF));
366 F_STRING *string = untag_string(dpeek());
367 sbuf->top = string->length;
368 sbuf->string = tag_object(string);
369 drepl(tag_object(sbuf));
372 void primitive_hashtable(void)
374 F_HASHTABLE* hash = allot_object(HASHTABLE_TYPE,sizeof(F_HASHTABLE));
378 dpush(tag_object(hash));
381 void update_xt(F_WORD* word)
384 word->xt = primitive_to_xt(to_fixnum(word->primitive));
387 /* <word> ( name vocabulary -- word ) */
388 F_WORD *allot_word(CELL vocab, CELL name)
390 REGISTER_ROOT(vocab);
392 F_WORD *word = allot_object(WORD_TYPE,sizeof(F_WORD));
393 UNREGISTER_ROOT(name);
394 UNREGISTER_ROOT(vocab);
395 word->hashcode = tag_fixnum(rand());
396 word->vocabulary = vocab;
398 word->primitive = tag_fixnum(0);
405 void primitive_word(void)
409 dpush(tag_word(allot_word(vocab,name)));
412 void primitive_update_xt(void)
414 update_xt(untag_word(dpop()));
417 void primitive_word_xt(void)
419 F_WORD *word = untag_word(dpeek());
420 drepl(allot_cell(word->xt));
423 void fixup_word(F_WORD* word)
425 /* If this is a compiled word, relocate the code pointer. Otherwise,
426 reset it based on the primitive number of the word. */
427 if(word->compiledp != F)
428 code_fixup(&word->xt);
433 void primitive_wrapper(void)
435 F_WRAPPER *wrapper = allot_object(WRAPPER_TYPE,sizeof(F_WRAPPER));
436 wrapper->object = dpeek();
437 drepl(tag_wrapper(wrapper));