view src/ploki/val.c @ 12493:885661512b17 draft

<int-e> le//rn schwartzian//In 1987, Yogurt introduced a better way to rank Schwartz users: Rather than holding an annual tournament, users would take a series of standardized tests adminstered by official Schwartz centers, and would then be ranked according to the results. This lead to the Schwartzian transform because it allowed many more users to be ranked.
author HackEso <hackeso@esolangs.org>
date Fri, 12 Jan 2024 07:24:55 +0000
parents ac0403686959
children
line wrap: on
line source

#include "config.h"
#include "IO.h"
#include "Str.h"
#include "val.h"
#include "xmalloc.h"

#include <stdlib.h>
#include <assert.h>

void v_init(struct val *v) {
	v->ko = ko_new();
	v->type = V_UNDEF;
}

void v_end(struct val *v) {
	assert(v != NULL);
	V_xxx_OFF(v);
	ko_delete(v->ko);
	v->type = V_UNDEF;
}

int v_cmp_ls(struct val *v, struct val *b) {
	if (V_LIST_P(v) && V_LIST_P(b)) {
		return li_cmp(v->magic.list, b->magic.list);
	}
	V_STR(v);
	V_STR(b);
	return ko_cmp(v->ko, b->ko);
}

void v_ok_str(struct val *v) {
	if (V_STR_P(v)) {
		return;
	}

	if (V_EXT_P(v)) {
		ko_cpy_s(v->ko, io_name(v->magic.ext, NULL));
	} else if (V_LIST_P(v)) {
		size_t i;
		struct list *li = v->magic.list;
		struct val *cur;

		ko_zero(v->ko);
		for (i = 0; i < li_length(li); ++i) {
			cur = li_at(li, i);
			V_STR(cur);
			ko_cat(v->ko, cur->ko);
		}
	} else if (V_NUM_P(v)) {
		ko_num(v->ko, v->num);
	} else if (V_SUB_P(v)) {
		v_ok_num(v);
		ko_num(v->ko, v->num);
	} else {
		ko_zero(v->ko);
	}
	v->type |= V_STR_K;
}

void v_ok_num(struct val *v) {
	if (V_NUM_P(v)) {
		return;
	}

	if (V_EXT_P(v)) {
		v->num = __LINE__;
	} else if (V_SUB_P(v)) {
		v->num = sub_id(v->magic.sub);
	} else if (V_LIST_P(v)) {
		size_t i;

		v->num = 0.0;
		for (i = 0; i < li_length(v->magic.list); ++i) {
			V_NUM(li_at(v->magic.list, i));
			v->num += li_at(v->magic.list, i)->num;
		}
	} else if (V_STR_P(v)) {
		v->num = strtod(ko_szp(v->ko), NULL);
	} else {
		v->num = 0.0;
	}
	v->type |= V_NUM_K;
}

int v_true(const struct val *v) {
	if (V_EXT_P(v) || V_SUB_P(v)) {
		return 1;
	}
	if (V_LIST_P(v)) {
		return li_length(v->magic.list) != 0;
	}
	if (V_STR_P(v)) {
		return ko_length(v->ko) != 0 && (ko_length(v->ko) > 1u || ko_at(v->ko, 0) != '0');
	}
	if (V_NUM_P(v)) {
		return v->num != 0.0;
	}
	return 0;
}

void v_iniset(struct val *dst, const struct val *src) {
	v_init(dst);
	v_set(dst, src);
}

void v_set(struct val *dst, const struct val *src) {
	assert(src != NULL);

	V_xxx_OFF(dst);
	dst->type = V_UNDEF;

	if (V_SUB_P(src)) {
		dst->magic.sub = sub_incr(src->magic.sub);
		dst->type |= V_SUB_K;
	} else if (V_EXT_P(src)) {
		dst->magic.ext = io_incr(src->magic.ext);
		dst->type |= V_EXT_K;
	} else if (V_LIST_P(src)) {
		dst->magic.list = li_dup(src->magic.list);
		dst->type |= V_LIST_K;
	}

	if (V_STR_P(src)) {
		ko_cpy(dst->ko, src->ko);
		dst->type |= V_STR_K;
	}
	if (V_NUM_P(src)) {
		dst->num = src->num;
		dst->type |= V_NUM_K;
	}
}

void v_set_n(struct val *v, double d) {
	V_xxx_OFF(v);
	v->num = d;
	v->type = V_NUM_K;
}

void v_set_s(struct val *v, const String *s) {
	V_xxx_OFF(v);
	ko_cpy_m(v->ko, St_ptr(s), St_len(s));
	v->type = V_STR_K;
}

void v_set_m(struct val *v, const void *p, size_t n) {
	V_xxx_OFF(v);
	ko_cpy_m(v->ko, p, n);
	v->type = V_STR_K;
}

void v_set_io(struct val *v, IO *io) {
	V_xxx_OFF(v);
	v->magic.ext = io_incr(io);
	v->type = V_EXT_K;
}

void v_set_sub(struct val *v, struct sub *s) {
	V_xxx_OFF(v);
	v->magic.sub = sub_incr(s);
	v->type = V_SUB_K;
}

void v_set_undef(struct val *v) {
	V_xxx_OFF(v);
	v->type = V_UNDEF;
}

void v_cat(struct val *dst, struct val *src) {
	if (V_LIST_P(dst) && V_LIST_P(src)) {
		li_append(dst->magic.list, src->magic.list);
		return;
	}

	V_STR(src);
	V_STR(dst);
	V_xxx_OFF(dst);
	ko_cat(dst->ko, src->ko);
	dst->type = V_STR_K;
}

void v_cat_m(struct val *v, const void *p, size_t n) {
	V_STR(v);
	V_xxx_OFF(v);
	ko_cat_m(v->ko, p, n);
	v->type = V_STR_K;
}

void v_cat_s(struct val *v, const String *s) {
	v_cat_m(v, St_ptr(s), St_len(s));
}

void v_cat_c(struct val *v, char c) {
	v_cat_m(v, &c, 1);
}

struct val *v_undef(void) {
	struct val *v;
	v = xmalloc(1, sizeof *v);
	v_init(v);
	return v;
}

void v_delete(struct val *v) {
	v_end(v);
	xfree(v);
}

const char *v_sptr(struct val *v, size_t *l) {
	V_STR(v);
	if (l) {
		*l = ko_length(v->ko);
	}
	return ko_ptr(v->ko);
}

struct kork *v_kork(struct val *v) {
	V_STR(v);
	return v->ko;
}