1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
|
/* term.c -- operations on terms ($Revision: 1.1.1.1 $) */
#include "es.h"
#include "gc.h"
#include "term.h"
DefineTag(Term, static);
extern Term *mkterm(char *str, Closure *closure) {
gcdisable();
Ref(Term *, term, gcnew(Term));
term->str = str;
term->closure = closure;
gcenable();
RefReturn(term);
}
extern Term *mkstr(char *str) {
Term *term;
Ref(char *, string, str);
term = gcnew(Term);
term->str = string;
term->closure = NULL;
RefEnd(string);
return term;
}
extern Closure *getclosure(Term *term) {
if (term->closure == NULL) {
char *s = term->str;
assert(s != NULL);
if (
((*s == '{' || *s == '@') && s[strlen(s) - 1] == '}')
|| (*s == '$' && s[1] == '&')
|| hasprefix(s, "%closure")
) {
Ref(Term *, tp, term);
Ref(Tree *, np, parsestring(s));
if (np == NULL) {
RefPop2(np, tp);
return NULL;
}
tp->closure = extractbindings(np);
tp->str = NULL;
term = tp;
RefEnd2(np, tp);
}
}
return term->closure;
}
extern char *getstr(Term *term) {
char *s = term->str;
Closure *closure = term->closure;
assert((s == NULL) != (closure == NULL));
if (s != NULL)
return s;
#if 0 /* TODO: decide whether getstr() leaves term in closure or string form */
Ref(Term *, tp, term);
s = str("%C", closure);
tp->str = s;
tp->closure = NULL;
RefEnd(tp);
return s;
#else
return str("%C", closure);
#endif
}
extern Term *termcat(Term *t1, Term *t2) {
if (t1 == NULL)
return t2;
if (t2 == NULL)
return t1;
Ref(Term *, term, mkstr(NULL));
Ref(char *, str1, getstr(t1));
Ref(char *, str2, getstr(t2));
term->str = str("%s%s", str1, str2);
RefEnd2(str2, str1);
RefReturn(term);
}
static void *TermCopy(void *op) {
void *np = gcnew(Term);
memcpy(np, op, sizeof (Term));
return np;
}
static size_t TermScan(void *p) {
Term *term = p;
term->closure = forward(term->closure);
term->str = forward(term->str);
return sizeof (Term);
}
extern Boolean termeq(Term *term, const char *s) {
assert(term != NULL);
if (term->str == NULL)
return FALSE;
return streq(term->str, s);
}
extern Boolean isclosure(Term *term) {
assert(term != NULL);
return term->closure != NULL;
}
|