My macro can receive either a variable, say 'x' or a complex expression, say f()
or x + y
. I want it to do x = 1
in case it is a single variable and do nothing if it was f()
, how to acieve this behaviour?
My own programming language compiler compiles to C if anyone wonders why I need this.
Another way to look at this is that I may need to get a pointer of a provided argument if that's possible and do nothing otherwise. Or basically I need IS_LVALUE(x)
macro. Similarly to IS_CONST_EXPR(x)
found in Linux source code.
#define __index_set_macro(object, ix, item) \
({ val _T = object; \
if (__is_int(_T) && __is_int(ix) && __is_int(item)) \
_T ^= (-(!!item) ^ _T) & (1UL << ix); \
object = _T; \
else __index_set(_T, ix, item); })
void __index_set(val object, val index, val item) {
if (__is_heap(object)) {
leaf *l = __leaf(object);
switch (l->type) {
case leaf_arr:
if (!__is_num(index)) __throw_n(__str(E004_0), 2);
*__array_at(object, __get(index)) = item;
return;
case leaf_obj:
__property_set(object, index, item);
return;
default:
__throw_n(__tem(E008_1, __type_of(object)), 3);
}
}
else {
__throw_n(__tem(E008_1, __type_of(object)), 3);
}
}
val
is a boxed value which is treated as int32_t
if the most significant bit is zero or as a pointer to a struct
on heap otherwise. I need a function __set_index(object, index, item)
that works with both, i.e. in my language you can write:
a := 0
a[0] = 1 // i.e. you set bit
b := [0 1 2 3] // create an array
b[0] = 123 // you change the value of the first item
which is compiled to:
val a = __let(0);
__set_index(a, 0, 1);
val b = __array(4, (val[]){0, 1, 2, 3});
__set_index(b, 0, 123);
as you can see I need __set_index
to distinguish at runtime either it does a = some bit operations(a)
or ((heap_object*)b)->table)[index] = item;