ucg/std/tuples.ucg
Jeremy Wall a90df8a362 REFACTOR: Cleanup the syntax for the select expr
This makes it both easier to correctly write a select expression
as well as easier to parse and report syntax errors.
2019-11-02 11:01:47 -05:00

115 lines
3.5 KiB
Plaintext

// Assert that a value is a tuple. Generate a compile failure if it is not.
let assert_tuple = func (tpl) => select (tpl is "tuple", NULL) => {
false = fail "@ is not a tuple" % (tpl),
};
// Return a list of the fields in a tuple.
let fields = module{
tpl = NULL,
} => (result) {
let assert_tuple = import "std/tuples.ucg".assert_tuple;
// First we check that mod.tpl is a tuple.
assert_tuple(mod.tpl);
let result = reduce(func (acc, field, value) => acc + [field], [], (mod.tpl));
};
// Return a list of the values in a tuple.
let values = module{
tpl = NULL,
} => (result) {
let assert_tuple = import "std/tuples.ucg".assert_tuple;
// First we check that mod.tpl is a tuple.
assert_tuple(mod.tpl);
let result = reduce(func (acc, field, value) => acc + [value], [], (mod.tpl));
};
// Return a list of the key value pairs in the tuple.
let iter = module{
tpl = NULL,
} => (result) {
let assert_tuple = import "std/tuples.ucg".assert_tuple;
// First we check that mod.tpl is a tuple.
assert_tuple(mod.tpl);
let result = reduce(func (acc, field, value) => acc + [[field, value]], [], (mod.tpl));
};
// Wraps a tuple and provides a number of operations on it.
//
// * fields - function returns all the fields in the wrapped tuple as a list.
//
// * values - function returns all the values in the wrapped tuple as a list.
//
// * iter - function returns a list of pairs of [field, value].
let ops = module{
tpl = NULL,
} => ({fields=fields, values=values, iter=iter}) {
(mod.tpl != NULL) || fail "tpl must not be null";
let pkg = mod.pkg();
let fields = func() => pkg.fields{tpl=mod.tpl};
let values = func() => pkg.values{tpl=mod.tpl};
let iter = func() => pkg.iter{tpl=mod.tpl};
};
// Strip all the null fields from a tuple.
let strip_nulls = module{
tpl = NULL,
} => (result) {
let assert_tuple = import "std/tuples.ucg".assert_tuple;
// First we check that mod.tpl is a tuple.
assert_tuple(mod.tpl);
let result = filter(func (name, value) => value != NULL, (mod.tpl));
};
// Check if a tuple has all the fields in a given list.
let has_fields = module{
tpl = NULL,
fields = [],
} => (result) {
let pkg = mod.pkg();
// First we check that mod.tpl is a tuple.
pkg.assert_tuple(mod.tpl);
let fs = pkg.fields{tpl=mod.tpl};
let result = reduce(func (acc, f) => acc && (f in fs), true, mod.fields);
};
// Check if a field in a tuple is a given type.
let field_type = module{
tpl = NULL,
field = NULL,
type = NULL,
} => (result) {
let pkg = mod.pkg();
// First we check that mod.tpl is a tuple.
pkg.assert_tuple(mod.tpl);
// Next we assert that mod.field is a string.
select (mod.field is "str", NULL) => {
false = fail "@ is not a string" % (mod.field),
};
// and finally that mod.type is a string
select (mod.type is "str", NULL) => {
false = fail "@ is not a string" % (mod.type),
};
// Get the list of field value pairs.
let it = pkg.iter{tpl=mod.tpl};
// The reducer function used to check the field's types if it exists.
let reducer = func (acc, l) => acc && (select (l.0 == mod.field, NULL) => {
true = l.1 is mod.type, // if this is the field then we propagate if it's the right type.
false = true, // if this isn't the field then we propagate true
});
// The computed answer true or false.
let result = pkg.has_fields{tpl=mod.tpl, fields=[mod.field]} && reduce(reducer, true, it);
};