mirror of
https://github.com/johnkerl/miller.git
synced 2026-08-02 04:22:59 +00:00
352 lines
10 KiB
C
352 lines
10 KiB
C
#ifndef XVFUNCS_H
|
|
#define XVFUNCS_H
|
|
|
|
// ================================================================
|
|
// Functions on extended values, namely, scalars and maps.
|
|
//
|
|
// NOTE ON EPHEMERALITY OF MAPS:
|
|
//
|
|
// Most functions here free their inputs. E.g. for string concatenation, the
|
|
// output which is returned is the concatenation of the two inputs which are
|
|
// freed. This is true for functions on scalars as well as functions on maps
|
|
// (the latter in this header file).
|
|
//
|
|
// However, maps are treated differently from scalars in that some maps are
|
|
// referenced, rather than copied, within the concrete syntax tree. E.g. in
|
|
// 'mapsum({3:4},@v)', the map literal {3:4} is ephemeral to the expression and
|
|
// must be freed during evaluation, but the @v part is referenced to the @v data
|
|
// structure and is only copied on write. The boxed_xval_t's is_ephemeral flag
|
|
// tracks the difference between the two cases.
|
|
// ================================================================
|
|
|
|
#include "../lib/mlrutil.h"
|
|
#include "../containers/mlhmmv.h"
|
|
#include "../containers/boxed_xval.h"
|
|
|
|
// ----------------------------------------------------------------
|
|
typedef boxed_xval_t xv_variadic_func_t(
|
|
boxed_xval_t* pbxvals,
|
|
int nxvals);
|
|
|
|
typedef boxed_xval_t xv_zary_func_t();
|
|
|
|
typedef boxed_xval_t xv_unary_func_t(
|
|
boxed_xval_t* pbxval1);
|
|
|
|
typedef boxed_xval_t xv_binary_func_t(
|
|
boxed_xval_t* pbxval1,
|
|
boxed_xval_t* pbxval2);
|
|
|
|
typedef boxed_xval_t xv_ternary_func_t(
|
|
boxed_xval_t* pbxval1,
|
|
boxed_xval_t* pbxval2,
|
|
boxed_xval_t* pbxval3);
|
|
|
|
// ----------------------------------------------------------------
|
|
// Most functions here free their inputs. E.g. for string concatenation, the
|
|
// output which is returned is the concatenation of the two inputs which are
|
|
// freed. For another example, is_string frees its input and returns the boolean
|
|
// value of the result. These functions, by contrast, only return a boolean for
|
|
// the outcome of the test but do not free the inputs. The intended usage is for
|
|
// type-assertion checks. E.g. in '$b = asserting_string($a)', if $a is a
|
|
// string it is assigned to $b, else an error is thrown.
|
|
|
|
static inline boxed_xval_t b_x_is_present_no_free_xfunc(boxed_xval_t* pbxval1) {
|
|
return box_ephemeral_val(
|
|
mv_from_bool(
|
|
!pbxval1->xval.is_terminal || mv_is_present(&pbxval1->xval.terminal_mlrval)
|
|
)
|
|
);
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_absent_no_free_xfunc(boxed_xval_t* pbxval1) {
|
|
return box_ephemeral_val(
|
|
mv_from_bool(
|
|
pbxval1->xval.is_terminal && mv_is_absent(&pbxval1->xval.terminal_mlrval)
|
|
)
|
|
);
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_map_no_free_xfunc(boxed_xval_t* pbxval1) {
|
|
return box_ephemeral_val(
|
|
mv_from_bool(
|
|
!pbxval1->xval.is_terminal
|
|
)
|
|
);
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_not_map_no_free_xfunc(boxed_xval_t* pbxval1) {
|
|
return box_ephemeral_val(
|
|
mv_from_bool(
|
|
pbxval1->xval.is_terminal
|
|
)
|
|
);
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_numeric_no_free_xfunc(boxed_xval_t* pbxval1) {
|
|
return box_ephemeral_val(
|
|
mv_from_bool(
|
|
pbxval1->xval.is_terminal && mv_is_numeric(&pbxval1->xval.terminal_mlrval)
|
|
)
|
|
);
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_int_no_free_xfunc(boxed_xval_t* pbxval1) {
|
|
return box_ephemeral_val(
|
|
mv_from_bool(
|
|
pbxval1->xval.is_terminal && mv_is_int(&pbxval1->xval.terminal_mlrval)
|
|
)
|
|
);
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_float_no_free_xfunc(boxed_xval_t* pbxval1) {
|
|
return box_ephemeral_val(
|
|
mv_from_bool(
|
|
pbxval1->xval.is_terminal && mv_is_float(&pbxval1->xval.terminal_mlrval)
|
|
)
|
|
);
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_boolean_no_free_xfunc(boxed_xval_t* pbxval1) {
|
|
return box_ephemeral_val(
|
|
mv_from_bool(
|
|
pbxval1->xval.is_terminal && mv_is_boolean(&pbxval1->xval.terminal_mlrval)
|
|
)
|
|
);
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_string_no_free_xfunc(boxed_xval_t* pbxval1) {
|
|
return box_ephemeral_val(
|
|
mv_from_bool(
|
|
pbxval1->xval.is_terminal && mv_is_string(&pbxval1->xval.terminal_mlrval)
|
|
)
|
|
);
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_null_no_free_xfunc(boxed_xval_t* pbxval1) {
|
|
return box_ephemeral_val(
|
|
mv_from_bool(
|
|
pbxval1->xval.is_terminal && mv_is_null(&pbxval1->xval.terminal_mlrval)
|
|
)
|
|
);
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_not_null_no_free_xfunc(boxed_xval_t* pbxval1) {
|
|
return box_ephemeral_val(
|
|
mv_from_bool(
|
|
!(pbxval1->xval.is_terminal && mv_is_null(&pbxval1->xval.terminal_mlrval))
|
|
)
|
|
);
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_empty_no_free_xfunc(boxed_xval_t* pbxval1) {
|
|
return box_ephemeral_val(
|
|
mv_from_bool(
|
|
pbxval1->xval.is_terminal && mv_is_empty(&pbxval1->xval.terminal_mlrval)
|
|
)
|
|
);
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_not_empty_no_free_xfunc(boxed_xval_t* pbxval1) {
|
|
return box_ephemeral_val(
|
|
mv_from_bool(
|
|
!(pbxval1->xval.is_terminal && mv_is_empty(&pbxval1->xval.terminal_mlrval))
|
|
)
|
|
);
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_empty_map_no_free_xfunc(boxed_xval_t* pbxval1) {
|
|
return box_ephemeral_val(
|
|
mv_from_bool(
|
|
!pbxval1->xval.is_terminal && pbxval1->xval.pnext_level->num_occupied == 0
|
|
)
|
|
);
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_nonempty_map_no_free_xfunc(boxed_xval_t* pbxval1) {
|
|
return box_ephemeral_val(
|
|
mv_from_bool(
|
|
!pbxval1->xval.is_terminal && pbxval1->xval.pnext_level->num_occupied != 0
|
|
)
|
|
);
|
|
}
|
|
|
|
static inline boxed_xval_t s_x_typeof_no_free_xfunc(boxed_xval_t* pbxval1) {
|
|
return box_ephemeral_val(
|
|
mv_from_string(
|
|
mlhmmv_xvalue_describe_type_simple(&pbxval1->xval), NO_FREE
|
|
)
|
|
);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
static inline boxed_xval_t b_x_is_present_xfunc(boxed_xval_t* pbxval1) {
|
|
boxed_xval_t rv = b_x_is_present_no_free_xfunc(pbxval1);
|
|
if (pbxval1->is_ephemeral)
|
|
mlhmmv_xvalue_free(&pbxval1->xval);
|
|
return rv;
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_absent_xfunc(boxed_xval_t* pbxval1) {
|
|
boxed_xval_t rv = b_x_is_absent_no_free_xfunc(pbxval1);
|
|
if (pbxval1->is_ephemeral)
|
|
mlhmmv_xvalue_free(&pbxval1->xval);
|
|
return rv;
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_map_xfunc(boxed_xval_t* pbxval1) {
|
|
boxed_xval_t rv = b_x_is_map_no_free_xfunc(pbxval1);
|
|
if (pbxval1->is_ephemeral)
|
|
mlhmmv_xvalue_free(&pbxval1->xval);
|
|
return rv;
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_not_map_xfunc(boxed_xval_t* pbxval1) {
|
|
boxed_xval_t rv = b_x_is_not_map_no_free_xfunc(pbxval1);
|
|
if (pbxval1->is_ephemeral)
|
|
mlhmmv_xvalue_free(&pbxval1->xval);
|
|
return rv;
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_numeric_xfunc(boxed_xval_t* pbxval1) {
|
|
boxed_xval_t rv = b_x_is_numeric_no_free_xfunc(pbxval1);
|
|
if (pbxval1->is_ephemeral)
|
|
mlhmmv_xvalue_free(&pbxval1->xval);
|
|
return rv;
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_int_xfunc(boxed_xval_t* pbxval1) {
|
|
boxed_xval_t rv = b_x_is_int_no_free_xfunc(pbxval1);
|
|
if (pbxval1->is_ephemeral)
|
|
mlhmmv_xvalue_free(&pbxval1->xval);
|
|
return rv;
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_float_xfunc(boxed_xval_t* pbxval1) {
|
|
boxed_xval_t rv = b_x_is_float_no_free_xfunc(pbxval1);
|
|
if (pbxval1->is_ephemeral)
|
|
mlhmmv_xvalue_free(&pbxval1->xval);
|
|
return rv;
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_boolean_xfunc(boxed_xval_t* pbxval1) {
|
|
boxed_xval_t rv = b_x_is_boolean_no_free_xfunc(pbxval1);
|
|
if (pbxval1->is_ephemeral)
|
|
mlhmmv_xvalue_free(&pbxval1->xval);
|
|
return rv;
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_string_xfunc(boxed_xval_t* pbxval1) {
|
|
boxed_xval_t rv = b_x_is_string_no_free_xfunc(pbxval1);
|
|
if (pbxval1->is_ephemeral)
|
|
mlhmmv_xvalue_free(&pbxval1->xval);
|
|
return rv;
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_null_xfunc(boxed_xval_t* pbxval1) {
|
|
boxed_xval_t rv = b_x_is_null_no_free_xfunc(pbxval1);
|
|
if (pbxval1->is_ephemeral)
|
|
mlhmmv_xvalue_free(&pbxval1->xval);
|
|
return rv;
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_not_null_xfunc(boxed_xval_t* pbxval1) {
|
|
boxed_xval_t rv = b_x_is_not_null_no_free_xfunc(pbxval1);
|
|
if (pbxval1->is_ephemeral)
|
|
mlhmmv_xvalue_free(&pbxval1->xval);
|
|
return rv;
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_empty_xfunc(boxed_xval_t* pbxval1) {
|
|
boxed_xval_t rv = b_x_is_empty_no_free_xfunc(pbxval1);
|
|
if (pbxval1->is_ephemeral)
|
|
mlhmmv_xvalue_free(&pbxval1->xval);
|
|
return rv;
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_not_empty_xfunc(boxed_xval_t* pbxval1) {
|
|
boxed_xval_t rv = b_x_is_not_empty_no_free_xfunc(pbxval1);
|
|
if (pbxval1->is_ephemeral)
|
|
mlhmmv_xvalue_free(&pbxval1->xval);
|
|
return rv;
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_empty_map_xfunc(boxed_xval_t* pbxval1) {
|
|
boxed_xval_t rv = b_x_is_empty_map_no_free_xfunc(pbxval1);
|
|
if (pbxval1->is_ephemeral)
|
|
mlhmmv_xvalue_free(&pbxval1->xval);
|
|
return rv;
|
|
}
|
|
|
|
static inline boxed_xval_t b_x_is_nonempty_map_xfunc(boxed_xval_t* pbxval1) {
|
|
boxed_xval_t rv = b_x_is_nonempty_map_no_free_xfunc(pbxval1);
|
|
if (pbxval1->is_ephemeral)
|
|
mlhmmv_xvalue_free(&pbxval1->xval);
|
|
return rv;
|
|
}
|
|
|
|
static inline boxed_xval_t s_x_typeof_xfunc(boxed_xval_t* pbxval1) {
|
|
boxed_xval_t rv = s_x_typeof_no_free_xfunc(pbxval1);
|
|
if (pbxval1->is_ephemeral)
|
|
mlhmmv_xvalue_free(&pbxval1->xval);
|
|
return rv;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
boxed_xval_t b_xx_haskey_xfunc(
|
|
boxed_xval_t* pmapval,
|
|
boxed_xval_t* pkeyval);
|
|
|
|
boxed_xval_t i_x_length_xfunc(
|
|
boxed_xval_t* pbxval1);
|
|
|
|
boxed_xval_t i_x_depth_xfunc(
|
|
boxed_xval_t* pbxval1);
|
|
|
|
boxed_xval_t i_x_leafcount_xfunc(
|
|
boxed_xval_t* pbxval1);
|
|
|
|
boxed_xval_t variadic_mapsum_xfunc(
|
|
boxed_xval_t* pbxvals, int nxvals);
|
|
|
|
boxed_xval_t variadic_mapdiff_xfunc(
|
|
boxed_xval_t* pbxvals, int nxvals);
|
|
|
|
boxed_xval_t variadic_mapexcept_xfunc(
|
|
boxed_xval_t* pbxvals, int nxvals);
|
|
|
|
boxed_xval_t variadic_mapselect_xfunc(
|
|
boxed_xval_t* pbxvals, int nxvals);
|
|
|
|
boxed_xval_t m_ss_splitnv_xfunc(
|
|
boxed_xval_t* pstringval,
|
|
boxed_xval_t* psepval);
|
|
|
|
boxed_xval_t m_ss_splitnvx_xfunc(
|
|
boxed_xval_t* pstringval,
|
|
boxed_xval_t* psepval);
|
|
|
|
boxed_xval_t m_sss_splitkv_xfunc(
|
|
boxed_xval_t* pstringval,
|
|
boxed_xval_t* ppairsepval,
|
|
boxed_xval_t* plistsepval);
|
|
|
|
boxed_xval_t m_sss_splitkvx_xfunc(
|
|
boxed_xval_t* pstringval,
|
|
boxed_xval_t* ppairsepval,
|
|
boxed_xval_t* plistsepval);
|
|
|
|
boxed_xval_t s_ms_joink_xfunc(
|
|
boxed_xval_t* pmapval,
|
|
boxed_xval_t* psepval);
|
|
|
|
boxed_xval_t s_ms_joinv_xfunc(
|
|
boxed_xval_t* pmapval,
|
|
boxed_xval_t* psepval);
|
|
|
|
boxed_xval_t s_mss_joinkv_xfunc(
|
|
boxed_xval_t* pmapval,
|
|
boxed_xval_t* ppairsepval,
|
|
boxed_xval_t* plistsepval);
|
|
|
|
#endif // XVFUNCS_H
|