forked from wryun/es-shell
-
Notifications
You must be signed in to change notification settings - Fork 0
/
term.c
109 lines (95 loc) · 2.13 KB
/
term.c
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;
}