2 Copyright (C) 2017-2018 Keziah Wesley
4 You can redistribute and/or modify this file under the terms of the
5 GNU Affero General Public License as published by the Free Software
6 Foundation, either version 3 of the License, or (at your option) any
9 This file is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Affero General Public License for more details.
14 You should have received a copy of the GNU Affero General Public
15 License along with this file. If not, see
16 <http://www.gnu.org/licenses/>.
29 typedef uint32_t evaltype;
34 TYPEPRIM_LOSE = 0x00000000,
35 TYPEPRIM_FIX32 = 0x00010000,
36 TYPEPRIM_FIX64 = 0x00020000,
37 TYPEPRIM_LIST = 0x00030000,
38 TYPEPRIM_VECTOR = 0x00040000,
39 TYPEPRIM_UVECTOR = 0x00050000,
40 TYPEPRIM_SUBR = 0x00060000,
41 TYPEPRIM_ATOM = 0x00070000,
44 TYPEPRIM_NOPOOL_MASK = 0x70000000,
45 TYPEPRIM_VECTOR_BODY = 0x70000000,
46 TYPEPRIM_TUPLE = 0x70010000,
48 // TYPEPRIM is half of EVALTYPE
49 TYPEPRIM_MASK = 0x7fff0000
54 EVALTYPE_LOSE = TYPEPRIM_LOSE,
56 EVALTYPE_FIX32 = TYPEPRIM_FIX32,
58 EVALTYPE_FIX64 = TYPEPRIM_FIX64,
60 EVALTYPE_LIST = TYPEPRIM_LIST,
64 EVALTYPE_VECTOR = TYPEPRIM_VECTOR,
66 EVALTYPE_UVECTOR = TYPEPRIM_UVECTOR,
69 EVALTYPE_SUBR = TYPEPRIM_SUBR,
71 EVALTYPE_ATOM = TYPEPRIM_ATOM,
73 EVALTYPE_VECTOR_BODY = TYPEPRIM_VECTOR_BODY,
76 EVALTYPE_TUPLE = TYPEPRIM_TUPLE,
79 static inline uint32_t
82 return x & TYPEPRIM_MASK;
86 TYPEPRIM_EQ (evaltype a, evaltype b)
88 return !((a ^ b) & TYPEPRIM_MASK);
103 An Object's value is accessed through a concrete `foo_object`
106 `object` can be used to refer to Objects of unspecified type, which
107 are opaque except for their `type` field. Checked downcasts can be
108 performed via the `as_foo` functions; unchecked downcasts via
109 `object.foo` (use only when type information is locally
110 obvious). Some objects can be upcast to more specific supertypes,
111 such as `pool_object` for objects that are known to be storeable in
114 The generic `object` type should not be used to accept parameters
115 that have constraints on their type, and should not be used to
116 return objects that are of a statically-known type. Encoding type
117 information in function signatures allows strictly local reasoning
121 typedef union object object;
126 // layout so that value can be upcast by reinterpreting as a fix64
127 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
130 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
134 #error Unusual endianness?
139 alignas (16) evaltype type;
146 alignas (8) int64_t n;
150 alignas (16) evaltype type;
157 alignas (8) uint32_t _pad;
162 alignas (16) evaltype type;
169 alignas (8) uint32_t len;
174 alignas (16) evaltype type;
181 alignas (8) uint32_t len;
186 alignas (16) evaltype type;
193 alignas (8) void (*fn) ();
197 alignas (16) evaltype type;
204 alignas (8) uint32_t namelen;
209 alignas (16) evaltype type;
217 /// no rest; is a NOPOOL type
220 /// allocation can be anywhere
227 alignas (16) evaltype type;
233 /// Value half of a poolable object, for storage in a uvector.
245 /// Object of a type that can be stored in the pool.
246 /// NB. a pool_object* can point outside the pool; contrast with pool_ptr.
247 typedef union pool_object
249 /// any pool object has a type and a rest
252 // NB. never take the address of these type-punned fields!
253 alignas (16) evaltype type;
257 /// objects of statically known type
261 vector_object vector;
262 uvector_object uvector;
269 /// any object has a type
272 // NB. never take the address of these type-punned fields!
273 alignas (16) evaltype type;
277 /// objects of statically known type
278 /// use as_X() for checked downcast
283 vector_object vector;
284 uvector_object uvector;
291 Initialization helpers.
294 static inline fix32_object
295 new_fix32 (int32_t n)
297 return (fix32_object)
299 .type = EVALTYPE_FIX32,.rest = 0,.val = (fix32_val)
305 static inline fix64_object
306 new_fix64 (int64_t n)
308 return (fix64_object)
310 .type = EVALTYPE_FIX64,.rest = 0,.val = (fix64_val)
316 static inline list_object
317 new_list (pool_ptr head)
321 .type = EVALTYPE_LIST,.rest = 0,.val = (list_val)
327 // TODO: take a dope_object like uvector
328 static inline vector_object
329 new_vector (heap_ptr body, uint32_t length)
331 return (vector_object)
333 .type = EVALTYPE_VECTOR,.rest = 0,.val = (vector_val)
335 .len = length,.body = body}
339 static inline uvector_object
340 new_uvector (heap_ptr body, uint32_t length)
342 return (uvector_object)
344 .type = EVALTYPE_UVECTOR,.rest = 0,.val = (uvector_val)
346 .len = length,.body = body}
350 static inline tuple_object
351 new_tuple (object * body, uint32_t length)
353 return (tuple_object)
355 .type = EVALTYPE_TUPLE,.len = length,.body = body};
358 static inline subr_object
359 new_subr (void (*fn) ())
363 .type = EVALTYPE_SUBR,.rest = 0,.val = (subr_val)
369 static inline atom_object
370 new_atom (pool_ptr body, uint32_t namelen)
374 .type = EVALTYPE_ATOM,.rest = 0,.val = (atom_val)
376 .body = body,.namelen = namelen}
380 static inline dope_object
381 new_dope (uint32_t len, evaltype type)
385 .type = type,.grow = 0,.len = len,.gc = 0};
389 Common object operations.
392 uint32_t list_length (const list_object * o);
394 dope_object *vec_dope (const vector_object * o);
396 dope_object *uv_dope (const uvector_object * o);
398 static inline evaltype
399 utype (const uvector_object * o)
401 return uv_dope (o)->type;
404 // Change the EVALTYPE of an object. New type must have same PRIMTYPE.
406 chtype (object * o, evaltype type)
408 assert (TYPEPRIM_EQ (o->type, type));
412 // Allocate an vector of LOSEs and return a handle with length=0.
413 vector_object vector_create (uint32_t capacity);
415 // Stack-like interface to a VECTOR (with automatic GROW!)
416 object *stack_push (vector_object * v);
422 static inline fix32_object *
423 as_fix32 (object * o)
425 assert (TYPEPRIM_EQ (o->type, TYPEPRIM_FIX32));
429 static inline list_object *
432 assert (TYPEPRIM_EQ (o->type, EVALTYPE_LIST));
436 static inline vector_object *
437 as_vector (object * o)
439 assert (TYPEPRIM_EQ (o->type, EVALTYPE_VECTOR));
443 static inline uvector_object *
444 as_uvector (object * o)
446 assert (TYPEPRIM_EQ (o->type, EVALTYPE_UVECTOR));
450 static inline pool_object *
453 assert (!(TYPEPRIM (p->type) & TYPEPRIM_NOPOOL_MASK));
454 return (pool_object *) p;
457 static inline atom_object *
460 assert (TYPEPRIM_EQ (o->type, EVALTYPE_ATOM));