| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- /*
- * Abstract: Defining objects and values
- * License: AGL, see LICENSE file for copyright and license details.
- */
- #ifndef ma_obj_h
- #define ma_obj_h
- #include "ma_conf.h"
- /*
- * Macros defined below are both used to manipulate objects and
- * non NAN-TAGGING represented values, reason why they aren't
- * specific to `#if` body of the MA_NAN_TAGGING check.
- */
- /* Vary type 't' with the variant bits 'v', see Value */
- #define vary(t, v) ((t) | (v << 5))
- #define with_variant(v) ((v)->type & 0x7F)
- #define without_variant(v) ((v)->type & 0x1F)
- #define check_type(v, t) (without_variant(v) == t)
- #define check_vartype(v, t) (with_variant(v) == t)
- /* Get top level value type of 'v' */
- #define vtype(v) with_variant(v)
- /* value 'o' is an object and get its object type */
- #define otype(o) with_variant(as_obj(v))
- /* Get profound type of 'v': dig into 'v' if it's an object */
- #define type(v) (ma_likely(is_obj(v)) ? otype(v) : vtype(v))
- #if !defined(MA_NAN_TAGGING)
- /*
- * $val: the value itself.
- * $n: representation of a number (see 'ma_conf.h').
- * $obj: pointer to an object, here, $val is an object.
- *
- * The below attributes are used to extend Maat code with C/C++:
- *
- * $cdata: pointer to C-class attributes('struct's).
- * $f: pointer to a C function, either represent a cdata's
- * method or just a standalone function.
- *
- * $type: determines $val's type, its bits are segmented into three
- * parts. This variable already gathers all what is necessary to
- * represent booleans and nils values.
- *
- * Bits distribution:
- *
- * - bits 0-4:
- * to represent the different types of values except for object
- * values which is determined by the MSB. If $val is an object
- * then bits 0-4 determine its object's type. This gives us a
- * maximum of 32 objects which suffices.
- *
- * - bits 5-6:
- * to represent variants of certain (O_)?TYPE_.* types. You can
- * have at most 3 variants for each base type which suffices.
- *
- * - bit 7: Mark bit: if 1 then $val is an object, 0 otherwise.
- */
- typedef struct {
- Ubyte type;
- union {
- struct Header *obj;
- Num n;
- CFunc f;
- void *cdata;
- } val;
- } Value;
- #define set_type(v, t) ((v)->type = t)
- #define set_val(v, val, t) set_type(v, t); ((v)->val = val);
- #define set_valo(v, o) set_val(v, o, (o)->type)
- /*
- * For objects, copy by reference v2 into v1 while
- * for non objects (numbers, etc), copy by value.
- */
- #define copy(v1, v2) set_val(v1, v2->val, v2->type)
- /*
- * All the possible standard types of a value, look! V_TYPE_OBJ
- * is also one. A value 'v' is an object if the MSB of its $type
- * is 1.
- */
- #define V_TYPE_NIL 0
- #define V_TYPE_BOOL 1
- #define V_TYPE_NUM 2
- #define V_TYPE_CFUNC 3
- #define V_TYPE_CDATA 4
- #define OBJ_BIT (0b1 << 7)
- #define is_obj(v) (type(v) & OBJ_BIT)
- #define is_num(v) check_type(v, V_TYPE_NUM)
- #define is_nil(v) check_type(v, V_TYPE_NIL)
- #define is_bool(v) check_type(v, V_TYPE_BOOL)
- #define is_cfunc(v) check_type(v, V_TYPE_CFUNC)
- #define is_cdata(v) check_type(v, V_TYPE_CDATA)
- /* Check if a value is collectable */
- #define is_ctb(v) is_obj(v)
- #define as_bool(v) (is_true(v))
- #define as_num(v) ((v)->val.n)
- #define as_obj(v) ((v)->val.obj)
- #define as_cfunc(v) ((v)->val.f)
- #define as_cdata(v) ((v)->val.cdata)
- /*
- * Define variants of the 'nil' type and its singleton values.
- *
- * V_TYPEV_FREE: this nil variant differentiates a key whose
- * corresponding value is a user-perceived 'nil' from a free
- * position in a hash table.
- *
- * V_TYPEV_ABSKEY: when indexing a hash table and key isn't
- * found, return a dummy value of type V_TYPEV_ABSKEY.
- */
- #define V_TYPEV_FREE vary(V_TYPE_NIL, 1)
- #define V_TYPEV_ABSKEY vary(V_TYPE_NIL, 2)
- #define FREE (Value){ V_TYPEV_FREE, { 0 } }
- #define ABSKEY (Value){ V_TYPEV_ABSKEY, { 0 } }
- #define is_strict_nil(v) check_vartype(v, V_TYPE_NIL)
- #define is_free(v) check_vartype(v, V_TYPEV_NILKEY)
- #define is_abskey(v) check_vartype(v, V_TYPEV_ABSKEY)
- /* Define boolean type variants with its singleton values */
- #define V_TYPEV_TRUE vary(V_TYPE_BOOL,1)
- #define V_TYPEV_FALSE vary(V_TYPE_BOOL,2)
- #define BOOL (Value){ V_TYPE_BOOL, { 0 } }
- #define TRUE (Value){ V_TYPEV_TRUE, { 0 } }
- #define FALSE (Value){ V_TYPEV_FALSE, { 0 } }
- #define is_false(v) check_vartype(to_bool(v), V_TYPEV_FALSE)
- #define is_true(v) check_vartype(to_bool(v), V_TYPEV_TRUE)
- #define to_bool(v) (ma_likely(is_bool(v)) ? v : coerce_to_bool(v))
- #else
- /*
- * TODO
- */
- typedef uint64_t Value;
- #endif
- /*
- * What? Header inherited by all the below objects
- * $type: type of the object
- * $mark: flag to mark the object during collection
- * $class: the object's class
- * $next: next obj,to keep track of all objects
- */
- typedef struct Header {
- Ubyte type;
- Ubyte mark;
- struct Class *class;
- struct Header *next;
- } Header;
- /* Test if the value 'v' is an object of type 't' */
- #define o_check_type(v, t) is_obj(v) && check_type(v, t)
- /* Defining of all base objects */
- #define O_TYPE_CLASS 5
- #define O_TYPE_STR 6
- #define O_TYPE_RANGE 7
- #define O_TYPE_ARRAY 8 /* variants: O_TYPEV_SET, O_TYPEV_MSET, O_TYPEV_LIST */
- #define O_TYPE_MAP 9 /* variants: O_TYPEV_BAG, O_TYPEV_MBAG */
- #define O_TYPE_FUN 10 /* variants: O_TYPEV_CLOSURE */
- #define O_TYPE_CO 12 /* variants: O_TYPEV_MA, O_TYPEV_WORK */
- #define O_TYPE_RBQ 13 /* variants: O_TYPEV_CHAN, O_TYPEV_SCHEDQ */
- #define O_TYPE_REGEX 14
- #define O_TYPE_SOCKET 15
- #define O_TYPE_PIPE 16
- #define O_TYPE_FILE 17
- #define O_TYPE_DIR 18
- #define O_TYPE_PROC 19
- #define O_TYPE_SYS 20
- #define O_TYPE_DATE 21
- #define O_TYPE_TERM 22
- #define O_DEADKEY 31 /* */
- /* A Check macro on 'v' for each object type */
- #define is_class(v) o_check_type(v, O_TYPE_CLASS)
- #define is_str(v) o_check_type(v, O_TYPE_STR)
- #define is_range(v) o_check_type(v, O_TYPE_RANGE)
- #define is_array(v) o_check_type(v, O_TYPE_ARRAY)
- #define is_map(v) o_check_type(v, O_TYPE_MAP)
- #define is_fun(v) o_check_type(v, O_TYPE_FUN)
- #define is_ma(v) o_check_type(v, O_TYPE_MA)
- #define is_rbq(v) o_check_type(v, O_TYPE_RBQ)
- #define is_regex(v) o_check_type(v, O_TYPE_REGEX)
- #define is_socket(v) o_check_type(v, O_TYPE_SOCKET)
- #define is_pipe(v) o_check_type(v, O_TYPE_PIPE)
- #define is_file(v) o_check_type(v, O_TYPE_FILE)
- #define is_dir(v) o_check_type(v, O_TYPE_DIR)
- #define is_proc(v) o_check_type(v, O_TYPE_PROC)
- #define is_date(v) o_check_type(v, O_TYPE_DATE)
- #define is_term(v) o_check_type(v, O_TYPE_TERM) /* See term.h */
- /* Test if the value 'v' is an object variant of variant type 't' */
- #define o_check_vartype(v,t) is_obj(v) && check_vartype(v,t)
- /* Here are variants of some base objects */
- /* Immutable and mutable bags */
- #define O_TYPEV_BAG vary(O_TYPE_MAP, 1)
- #define O_TYPEV_MBAG vary(O_TYPE_MAP, 2)
- #define is_bag(v) o_check_vartype(v, O_TYPEV_BAG)
- #define is_mbag(v) o_check_vartype(v, O_TYPEV_MBAG)
- /* Comma-separated list of values, immutable and mutable sets */
- #define O_TYPEV_LIST vary(O_TYPE_ARRAY, 1)
- #define O_TYPEV_SET vary(O_TYPE_ARRAY, 2)
- #define O_TYPEV_MSET vary(O_TYPE_ARRAY, 3)
- #define is_list(v) o_check_type(v, O_TYPE_LIST)
- #define is_set(v) o_check_vartype(v, O_TYPEV_SET)
- #define is_mset(v) o_check_vartype(v, O_TYPEV_MSET)
- /* A closure, it encapsulates upvalues */
- #define O_TYPEV_CLOSURE vary(O_TYPE_FUN, 1)
- #define is_closure(v) o_check_vartype(v, O_TYPEV_CLOSURE)
- #define O_TYPEV_MA vary(O_TYPE_CMA, 1)
- #define O_TYPEV_GFUN vary(O_TYPE_CMA, 1)
- #define O_TYPEV_MA vary(O_TYPE_CMA, 1)
- /* A threadsafe Channel and Scheduler queue */
- #define O_TYPEV_CHAN vary(O_TYPE_RBQ, 1)
- #define O_TYPEV_SCHEDQ vary(O_TYPE_RBQ, 2)
- #define is_chan(v) o_check_type(v, O_TYPEV_CHAN)
- #define is_schedq(v) o_check_type(v, O_TYPEV_SCHEDQ)
- /*
- * What? utf8 string object
- * $str: utf8 encoded string itself
- * $hash: hash value of $str
- * $rlen: real length of $str
- * $len: user-percieved length of $str
- */
- typedef struct {
- Header obj;
- Uint hash;
- size_t rlen;
- size_t len;
- Byte str[1];
- } Str;
- /*
- * What? Range object x..y
- * $x: the start (inclusive)
- * $y: the end (inclusive)
- */
- typedef struct {
- Header obj;
- Num x, y;
- } Range;
- typedef struct {
- Header obj;
- } Map;
- /*
- * $super: class' superclasses (C3 mro)
- * $name: class name
- * $nfields: number of fields
- * $methods: a Map for methods
- */
- typedef struct Class {
- Header obj;
- struct Class *super[1];
- Str *name;
- Ubyte nfields;
- Map *methods[1];
- } Class;
- /*
- */
- typedef struct {
- Header obj;
- //...
- } Fun;
- /*
- */
- typedef struct Upvalue {
- Header obj;
- Value *to;
- union {
- struct Upvalue *next;
- Value val;
- } state;
- } Upvalue;
- #endif
|