-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstack.c
223 lines (195 loc) · 4.73 KB
/
stack.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include "crossplatform/std.h"
#include "stack.h"
#include "run.h"
DEFINE_ENUM(VARIANTTYPE, ENUM_VARIANTTYPE);
Variant* stackidx(Runtime* R, long idx)
{
if (idx < 0) {
idx = R->stacksize + idx;
}
assert(idx < (int)R->stacksize && idx >= 0);
return &R->stack[idx];
}
void push(Runtime* R, Variant val)
{
try_stack_resize(R);
R->stack[R->stacksize++] = cpy_var(val);
}
void popn(Runtime *R, size_t count) {
for (size_t i = 0; i < count; ++i) {
Variant* ret = top(R);
free_var(*ret);
assert(R->stacksize >= 1);
R->stacksize--;
}
}
void pushstr(Runtime* R, char* str)
{
Variant var;
var.type = TYPE_STRING;
var.u.str = str;
push(R, var);
}
void pushlong(Runtime* R, int64_t n)
{
Variant var;
var.type = TYPE_LONG;
var.u.lint = n;
push(R, var);
}
void pushbool(Runtime* R, bool b)
{
Variant var;
var.type = TYPE_BOOL;
var.u.boolean = b;
push(R, var);
}
void pushnull(Runtime* R)
{
Variant var;
var.type = TYPE_NULL;
push(R, var);
}
void pushfunction(Runtime* R, Function* fn)
{
Variant var;
var.type = TYPE_FUNCTION;
var.u.function = fn;
push(R, var);
}
void pushcfunction(Runtime* R, CFunction* fn)
{
Variant var;
var.type = TYPE_CFUNCTION;
var.u.cfunction = fn;
push(R, var);
}
char* vartostring(Variant var)
{
char* buf;
switch (var.type) {
case TYPE_STRING:
assert(var.u.str);
return strdup(var.u.str);
case TYPE_LONG:
buf = malloc(sizeof(char) * 20); // Let this be "enough"
snprintf(buf, sizeof(char) * 20, "%" PRId64, var.u.lint);
return buf;
case TYPE_UNDEF:
return strdup("<UNDEFINED>");
case TYPE_NULL:
return strdup("<null>");
case TYPE_BOOL:
return var.u.boolean ? strdup("1") : strdup("");
case TYPE_FUNCTION:
case TYPE_CFUNCTION:
return strdup("function");
case TYPE_MAX_VALUE:
assert(false && "Undefined Type given");
break;
}
die("Assertion failed: May not reach end of tostring function.");
return NULL;
}
char* tostring(Runtime* R, int idx)
{
return vartostring(*stackidx(R, idx));
}
int64_t vartolong(Variant var)
{
long long ll = 0;
switch (var.type) {
case TYPE_UNDEF:
case TYPE_NULL:
return 0;
case TYPE_BOOL:
return var.u.boolean;
case TYPE_STRING:
ll = strtoll(var.u.str, NULL, 10);
int64_t lint = (int64_t) ll;
assert(ll == lint);
return lint;
case TYPE_LONG:
return var.u.lint;
case TYPE_FUNCTION:
case TYPE_CFUNCTION:
return 0;
case TYPE_MAX_VALUE:
assert(false && "Undefined Type given");
break;
}
die("tolong for undefined value.");
return 0;
}
int64_t tolong(Runtime* R, int idx)
{
return vartolong(*stackidx(R, idx));
}
bool vartobool(Variant var)
{
switch (var.type) {
case TYPE_UNDEF:
case TYPE_NULL:
return false;
case TYPE_LONG:
return var.u.lint != 0;
case TYPE_BOOL:
return var.u.boolean;
case TYPE_STRING:
if (var.u.str[0] == '\0' || (var.u.str[0] == '0' && var.u.str[1] == '\0')) {
return false;
} else {
return true;
}
case TYPE_FUNCTION:
case TYPE_CFUNCTION:
return false;
case TYPE_MAX_VALUE:
assert(false && "Undefined Type given");
break;
}
assert(false);
return false;
}
bool tobool(Runtime* R, int idx)
{
return vartobool(*stackidx(R, idx));
}
Variant vartotype(Variant var, VARIANTTYPE type)
{
if (var.type == type) {
return cpy_var(var);
}
Variant ret = {.type = TYPE_UNDEF, .u.lint = 0};
switch (type) {
case TYPE_STRING:
ret.type = TYPE_STRING;
ret.u.str = vartostring(var);
break;
case TYPE_LONG:
ret.type = TYPE_LONG;
ret.u.lint = vartolong(var);
break;
case TYPE_NULL:
ret.type = TYPE_NULL;
break;
case TYPE_UNDEF:
ret.type = TYPE_UNDEF;
break;
case TYPE_BOOL:
ret.type = TYPE_BOOL;
ret.u.boolean = vartobool(var);
break;
case TYPE_FUNCTION:
case TYPE_CFUNCTION:
die("Cannot convert function");
break;
case TYPE_MAX_VALUE:
assert(false && "Undefined Type given");
break;
}
return ret;
}