|
|
@@ -8,58 +8,57 @@
|
|
|
|
|
|
#include "ma_conf.h"
|
|
|
|
|
|
-/* Vary type 't' with the variant bits 'v' */
|
|
|
-#define vary(t,v) ((t) | (v << 5))
|
|
|
-
|
|
|
-#define with_variant(v) (v.type & 0x1F)
|
|
|
-#define without_variant(v) (v.type & 0x7F)
|
|
|
-#define check_type(v,t) (without_variant(v) == t)
|
|
|
-#define check_vartype(v,t) (with_variant(v) == t)
|
|
|
-
|
|
|
/*
|
|
|
- * Real type, real in the sense that we don't need to know whether
|
|
|
- * or not internally it is an object.
|
|
|
+ * 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.
|
|
|
*/
|
|
|
-#define rtype(v) (ma_likely(is_obj(v)) ? type(as_obj(v)) : type(v))
|
|
|
|
|
|
-#define set_type(o,t) ((o)->type = t)
|
|
|
-#define copy_obj(o1,o2) (o)
|
|
|
+/* Vary type 't' with the variant bits 'v', see Value */
|
|
|
+#define vary(t, v) ((t) | (v << 5))
|
|
|
|
|
|
-#if defined(MA_NAN_TAGGING)
|
|
|
+#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)
|
|
|
|
|
|
-/*
|
|
|
- * TODO
|
|
|
- */
|
|
|
-typedef uint64_t Value;
|
|
|
+/* 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))
|
|
|
|
|
|
-#else
|
|
|
+#if !defined(MA_NAN_TAGGING)
|
|
|
|
|
|
/*
|
|
|
* $val: the value itself.
|
|
|
- * $n: Maat's representation of a number(see 'ma_conf.h').
|
|
|
- * $obj: pointer to an object, value is an object.
|
|
|
+ * $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 functions, either represent a cdata's
|
|
|
+ * $f: pointer to a C function, either represent a cdata's
|
|
|
* method or just a standalone function.
|
|
|
*
|
|
|
- * $type: determines $val's type,this variable already gather all
|
|
|
- * what is necessary to represent booleans and nils values. It is
|
|
|
- * segmented into three parts.
|
|
|
+ * $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 is sufficient enough.
|
|
|
+ * maximum of 32 objects which suffices.
|
|
|
*
|
|
|
* - bits 5-6:
|
|
|
* to represent variants of certain (O_)?TYPE_.* types. You can
|
|
|
- * have at most 3 variants which is sufficient enough.
|
|
|
+ * have at most 3 variants for each base type which suffices.
|
|
|
*
|
|
|
* - bit 7: Mark bit: if 1 then $val is an object, 0 otherwise.
|
|
|
*/
|
|
|
@@ -73,10 +72,20 @@ typedef struct {
|
|
|
} 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 posible standard types of values except V_TYPE_OBJ type
|
|
|
- * marked by the MSB.
|
|
|
+ * 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
|
|
|
@@ -84,25 +93,23 @@ typedef struct {
|
|
|
#define V_TYPE_CFUNC 3
|
|
|
#define V_TYPE_CDATA 4
|
|
|
|
|
|
-#define type(v) with_variant(v)
|
|
|
-
|
|
|
#define OBJ_BIT (0b1 << 7)
|
|
|
|
|
|
-#define is_obj(v) (with_variant(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)
|
|
|
+#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_collectable(v) is_obj(v)
|
|
|
+#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 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.
|
|
|
@@ -111,18 +118,18 @@ typedef struct {
|
|
|
* corresponding value is a user-perceived 'nil' from a free
|
|
|
* position in a hash table.
|
|
|
*
|
|
|
- * V_TYPEV_ABSKEY: when indexing a hash table, return this value
|
|
|
- * when key isn't found.
|
|
|
+ * 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 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,NIL)
|
|
|
-#define is_free(v) check_vartype(v,V_TYPEV_NILKEY)
|
|
|
-#define is_abskey(v) check_vartype(v,V_TYPEV_ABSKEY)
|
|
|
+#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)
|
|
|
@@ -132,11 +139,18 @@ typedef struct {
|
|
|
#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 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
|
|
|
|
|
|
/*
|
|
|
@@ -154,7 +168,7 @@ typedef struct Header {
|
|
|
} 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)
|
|
|
+#define o_check_type(v, t) is_obj(v) && check_type(v, t)
|
|
|
|
|
|
/* Defining of all base objects */
|
|
|
#define O_TYPE_CLASS 5
|
|
|
@@ -177,22 +191,22 @@ typedef struct Header {
|
|
|
#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 */
|
|
|
+#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)
|
|
|
@@ -200,36 +214,36 @@ typedef struct Header {
|
|
|
/* 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 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)
|
|
|
+#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 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)
|
|
|
+#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 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)
|
|
|
+#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 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)
|
|
|
+#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
|