diff options
| author | Nakidai <nakidai@disroot.org> | 2026-04-05 19:51:14 +0300 |
|---|---|---|
| committer | Nakidai <nakidai@disroot.org> | 2026-04-05 20:01:32 +0300 |
| commit | 8afa976e073c7bc29c878230eead6dddfdcc08a1 (patch) | |
| tree | 044b8ddf87b9a3c8b5a229b27e84e870468fb950 /val.c | |
| download | thac-8afa976e073c7bc29c878230eead6dddfdcc08a1.tar.gz thac-8afa976e073c7bc29c878230eead6dddfdcc08a1.zip | |
Add code v0.1.0
Diffstat (limited to 'val.c')
| -rw-r--r-- | val.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/val.c b/val.c new file mode 100644 index 0000000..b8dc30d --- /dev/null +++ b/val.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2026 Nakidai Perumenei <nakidai at disroot dot org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "thac.h" + +#include <stdio.h> +#include <stdlib.h> + + +struct val +deref(struct val val, struct scope *scope) +{ + long i; + + if (val.type == VVAR) + { + i = findvar(val.name, &scope); + if (i < 0) + complain(1, "no such variable: %s", val.name); + val = scope->vars[i].val; + } + + return val; +} + +struct val +getval(enum val_t t, struct val val, struct scope *scope, int doderef) +{ + if (doderef) + val = deref(val, scope); + if (val.type != t) + complain(1, "expected %s, got %s", valname(t), valname(val.type)); + return val; +} + +struct val +copyval(struct val old) +{ + struct val new; + ulong i; + + new = old; + if (new.type == VARR) + { + new.arr = malloc(sizeof(*new.arr) * new.len); + if (!new.arr) + dieno(1, "malloc()"); + + for (i = 0; i < new.len; ++i) + new.arr[i] = copyval(old.arr[i]); + } + + return new; +} + +void +freeval(struct val val) +{ + ulong i; + + if (val.type == VARR) + { + for (i = 0; i < val.len; ++i) + freeval(val.arr[i]); + free(val.arr); + } +} + +static void +connectarr(struct val arr, ulong single, int arr_to_single) +{ + ulong i; + + for (i = 0; i < arr.len; ++i) switch (arr.arr[i].type) + { + break; case VARR: + connectarr(arr.arr[i], single, arr_to_single); + break; case VNUM: + if (arr_to_single) + addedge(arr.arr[i].num, single); + else + addedge(single, arr.arr[i].num); + break; default: complain(1, "%s can not be connected", valname(arr.arr[i].type)); + } +} + +static void +connectarrarr(struct val from, struct val to) +{ + ulong i; + + if (from.len != to.len) + complain(1, "cannot connect nonisomorphic arrays"); + + for (i = 0; i < from.len; ++i) + { + if (from.arr[i].type != to.arr[i].type) + complain(1, "cannot connect nonisomorphic arrays"); + switch (from.arr[i].type) + { + break; case VARR: connectarrarr(from.arr[i], to.arr[i]); + break; case VNUM: addedge(from.arr[i].num, to.arr[i].num); + break; default: complain(1, "%s can not be connected", valname(from.arr[i].type)); + } + } +} + +struct val +connectval(struct val refl, struct val refr, struct scope *scope) +{ + struct val l, r; + + l = deref(refl, scope); + r = deref(refr, scope); + + if (l.type == VNUM && r.type == VNUM) + addedge(r.num, l.num); + else if (l.type == VARR && r.type == VNUM) + connectarr(l, r.num, 0); + else if (l.type == VNUM && r.type == VARR) + connectarr(r, l.num, 1); + else if (l.type == VARR && r.type == VARR) + connectarrarr(r, l); + else + complain(1, "cannot connect %s and %s", valname(l.type), valname(r.type)); + + if (refr.type != VVAR) + freeval(r); + + return refl; +} |