-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathnv_term.c
250 lines (228 loc) · 6.32 KB
/
nv_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
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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
#include "nv.h"
//
// Type checks
//
int NV_Term_isNotFound(const NV_ID *id)
{
return NV_NodeID_isEqual(id, &NODEID_NOT_FOUND);
}
int NV_Term_isNull(const NV_ID *id)
{
return NV_NodeID_isEqual(id, &NODEID_NULL);
}
int NV_isTermType(const NV_ID *node, const NV_ID *tType)
{
NV_ID typeID = NV_NodeID_getRelatedNodeFrom(node, &RELID_TERM_TYPE);
return NV_NodeID_isEqual(&typeID, tType);
}
NV_ID NV_Term_tryReadAsVariableData(const NV_ID *id, const NV_ID *scope)
{
// 変数としてidが解釈できるなら、その変数の値に相当するidを返す
// 変数として解釈できる、とは
// - リテラルでない文字列で、コンテキストに存在する変数名と等しい
// - コンテキストはネストされている。元までたどる。
// - TermType === Variable
// 無理ならば、もとのidを返す
NV_ID vid;
//
vid = NV_Term_tryReadAsVariable(id, scope);
if(NV_isTermType(&vid, &NODEID_TERM_TYPE_VARIABLE)){
vid = NV_Variable_getData(&vid);
/*
printf("NV_Term_tryReadAsVariableData: variable!\n");
NV_Term_print(&vid);
printf("\n");
*/
if(!NV_NodeID_isEqual(&vid, &NODEID_NOT_FOUND)){
return vid;
}
}
return *id;
}
NV_ID NV_Term_tryReadAsVariable(const NV_ID *id, const NV_ID *scope)
{
// 変数としてidが解釈できるなら、その変数に相当するidを返す
// 変数として解釈できる、とは
// - リテラルでない文字列で、コンテキストに存在する変数名と等しい
// - コンテキストはネストされている。元までたどる。
// - TermType === Variable
// 無理ならば、もとのidを返す
//
if(NV_isTermType(id, &NODEID_TERM_TYPE_VARIABLE)){
// もともと変数オブジェクトだった
//printf("Already val obj\n");
return *id;
}
if(NV_NodeID_isString(id) && NV_Variable_statByName(scope, id)){
// 文字列でかつ現在のscopeに存在するのでその変数を返す
/*
printf("name \"%s\" found in context.\n",
NV_NodeID_getCStr(id));
*/
return NV_Variable_createWithName(scope, id);
}
// このコンテキスト階層では見つからなかったので、親があればたどる
NV_ID pCtx = NV_Dict_getEqID(scope, &RELID_PARENT_SCOPE);
if(!NV_NodeID_isEqual(&pCtx, &NODEID_NOT_FOUND)){
// 親の検索結果を返す
/*
if(IS_DEBUG_MODE()){
printf("Var NOT found. Search parent.\n");
}
*/
return NV_Term_tryReadAsVariable(id, &pCtx);
}
// あきらめる
/*
if(IS_DEBUG_MODE()){
printf("Var NOT found and has no parent.\n");
}
*/
return *id;
}
NV_ID NV_Term_getPrimNodeID(const NV_ID *id, const NV_ID *scope)
{
// 変数がネストされている場合は、一番外側の変数のみが展開される。
NV_ID n;
if(!id) return NODEID_NOT_FOUND;
n = *id;
if(1/* TODO: Add literal string check. */){
n = NV_Term_tryReadAsVariableData(&n, scope);
if(IS_DEBUG_MODE()){
printf("Var check result: ");
NV_Term_print(id);
printf(" -> ");
NV_Term_print(&n);
putchar('\n');
}
}
return n;
}
NV_ID NV_Term_getPrimNodeIDByCStr(const char *s, const NV_ID *scope)
{
NV_ID str = NV_Node_createWithString(s);
return NV_Term_getPrimNodeID(&str, scope);
}
/*
int NV_Term_isIntegerNotVal(const NV_ID *id)
{
// 整数ならそれを返す
if(NV_NodeID_isInteger(id)){
return 1;
}
// リテラルでない文字列ならば解釈を試みる
if(NV_NodeID_isString(id)){
// idはstringである。数値として解釈することを試みる。
int endi;
NV_NodeID_String_strtol(id, &endi, 0);
if((size_t)endi == NV_NodeID_String_strlen(id)){
// 文字列全体が整数として解釈できたのでこれは整数
return 1;
}
}
// どうやっても数値とは解釈できない
return 0;
}
*/
int NV_Term_isInteger(const NV_ID *id, const NV_ID *scope)
{
NV_ID n;
n = NV_Term_getPrimNodeID(id, scope);
if(NV_NodeID_isInteger(&n)) return 1;
if(NV_NodeID_isString(&n)){
int endi;
NV_Node_String_strtol(&n, &endi, 0);
if((size_t)endi == NV_Node_String_strlen(&n)){
// 文字列全体が整数として解釈できたのでこれは整数
return 1;
}
}
// 整数とは解釈できない
return 0;
}
int NV_Term_isAssignable(const NV_ID *id, const NV_ID *scope)
{
NV_ID vid;
vid = NV_Term_tryReadAsVariable(id, scope);
return NV_isTermType(&vid, &NODEID_TERM_TYPE_VARIABLE);
}
int NV_Term_isArray(const NV_ID *id, const NV_ID *scope)
{
NV_ID vid = NV_Term_tryReadAsVariableData(id, scope);
return NV_isTermType(&vid, &NODEID_TERM_TYPE_ARRAY);
}
//
// Read term data
//
int32_t NV_Term_getInt32(const NV_ID *id, const NV_ID *scope)
{
NV_ID n;
n = NV_Term_getPrimNodeID(id, scope);
if(NV_NodeID_isInteger(&n)) return NV_NodeID_getInt32(&n);
if(NV_NodeID_isString(&n)){
int endi;
int v;
v = NV_Node_String_strtol(&n, &endi, 0);
if((size_t)endi == NV_Node_String_strlen(&n)){
// 文字列全体が整数として解釈できたのでこれは整数
return v;
}
}
// 整数とは解釈できない
return -1;
}
NV_ID NV_Term_getAssignableNode(const NV_ID *id, const NV_ID *scope)
{
NV_ID vid;
if(NV_NodeID_isString(id) && NV_Variable_statByName(scope, id)){
// idが文字列でしかもそれに相当する変数が存在するなら変換
vid = NV_Variable_createWithName(scope, id);
id = &vid;
}
if(!NV_isTermType(id, &NODEID_TERM_TYPE_VARIABLE)) return NODEID_NOT_FOUND;
return *id;
}
//
// Assign to term
//
NV_ID NV_Term_assign(const NV_ID *v, const NV_ID *data)
{
// v: Path or Variable
/*
if(NV_isTermType(v, &NODEID_TERM_TYPE_PATH)){
NV_Path_assign(v, data);
} else
*/
if(NV_isTermType(v, &NODEID_TERM_TYPE_VARIABLE)){
NV_Variable_assign(v, data);
} else{
return NV_Node_createWithString("NV_Term_assign:Not assignable");
}
return NODEID_NULL;
}
//
// print
//
void NV_Term_print(const NV_ID *id)
{
if(NV_isTermType(id, &NODEID_TERM_TYPE_ARRAY)){
NV_Array_print(id);
} else if(NV_isTermType(id, &NODEID_TERM_TYPE_VARIABLE)){
NV_Variable_print(id);
} else if(NV_isTermType(id, &NODEID_TERM_TYPE_OP)){
NV_Lang_printOp(id);
} else{
NV_Node_printPrimVal(id);
}
}
int32_t NV_Term_calcHash(const NV_ID *id)
{
if(NV_isTermType(id, &NODEID_TERM_TYPE_ARRAY)){
return NV_Array_calcHash(id);
/*} else if(NV_isTermType(id, &NODEID_TERM_TYPE_VARIABLE)){
NV_Variable_print(id);
} else if(NV_isTermType(id, &NODEID_TERM_TYPE_OP)){
NV_printOp(id);*/
}
return NV_NodeID_calcHash(id);
}