1 | // frontend_flag_spec.cc
|
2 |
|
3 | #include "cpp/frontend_flag_spec.h"
|
4 |
|
5 | #include "_gen/frontend/arg_types.h"
|
6 | #include "mycpp/gc_builtins.h"
|
7 | // TODO: This prebuilt header should not be included in the tarball
|
8 | // for definition of args::Reader, etc.
|
9 | #include "prebuilt/frontend/args.mycpp.h"
|
10 |
|
11 | namespace flag_util {
|
12 |
|
13 | using runtime_asdl::flag_type_e;
|
14 | using value_asdl::value;
|
15 | using value_asdl::value_t;
|
16 |
|
17 | void _CreateStrList(const char** in, List<BigStr*>* out) {
|
18 | int i = 0;
|
19 | while (true) {
|
20 | const char* s = in[i];
|
21 | if (!s) {
|
22 | break;
|
23 | }
|
24 | // log("a0 %s", s);
|
25 | out->append(StrFromC(s));
|
26 | ++i;
|
27 | }
|
28 | }
|
29 |
|
30 | void _CreateDefaults(DefaultPair_c* in,
|
31 | Dict<BigStr*, value_asdl::value_t*>* out) {
|
32 | int i = 0;
|
33 | while (true) {
|
34 | DefaultPair_c* pair = &(in[i]);
|
35 | if (!pair->name) {
|
36 | break;
|
37 | }
|
38 | value_t* val;
|
39 | switch (pair->typ) {
|
40 | case flag_type_e::Bool:
|
41 | val = Alloc<value::Bool>(pair->val.b);
|
42 | break;
|
43 | case flag_type_e::Int:
|
44 | val = Alloc<value::Int>(pair->val.i);
|
45 | break;
|
46 | case flag_type_e::Float:
|
47 | val = Alloc<value::Float>(pair->val.f);
|
48 | break;
|
49 | case flag_type_e::Str: {
|
50 | const char* s = pair->val.s;
|
51 | if (s == nullptr) {
|
52 | val = value::Undef;
|
53 | } else {
|
54 | val = Alloc<value::Str>(StrFromC(s));
|
55 | }
|
56 | } break;
|
57 | default:
|
58 | FAIL(kShouldNotGetHere);
|
59 | }
|
60 | out->set(StrFromC(pair->name), val);
|
61 | ++i;
|
62 | }
|
63 | }
|
64 |
|
65 | void _CreateActions(Action_c* in, Dict<BigStr*, args::_Action*>* out) {
|
66 | int i = 0;
|
67 | while (true) {
|
68 | Action_c* p = &(in[i]);
|
69 | if (!p->key) {
|
70 | break;
|
71 | }
|
72 | // log("a1 %s", p->name);
|
73 | args::_Action* action = nullptr;
|
74 | switch (p->type) {
|
75 | case ActionType_c::SetToString: {
|
76 | List<BigStr*>* valid = nullptr;
|
77 | if (p->strs) {
|
78 | valid = NewList<BigStr*>();
|
79 | _CreateStrList(p->strs, valid);
|
80 | }
|
81 | auto a = Alloc<args::SetToString>(StrFromC(p->name), false, valid);
|
82 | action = a;
|
83 | } break;
|
84 | case ActionType_c::SetToString_q:
|
85 | action = Alloc<args::SetToString>(StrFromC(p->name), true, nullptr);
|
86 | break;
|
87 | case ActionType_c::SetToInt:
|
88 | action = Alloc<args::SetToInt>(StrFromC(p->name));
|
89 | break;
|
90 | case ActionType_c::SetToFloat:
|
91 | action = Alloc<args::SetToFloat>(StrFromC(p->name));
|
92 | break;
|
93 | case ActionType_c::SetToTrue:
|
94 | action = Alloc<args::SetToTrue>(StrFromC(p->name));
|
95 | break;
|
96 | case ActionType_c::SetAttachedBool:
|
97 | action = Alloc<args::SetAttachedBool>(StrFromC(p->name));
|
98 | break;
|
99 | case ActionType_c::SetOption:
|
100 | action = Alloc<args::SetOption>(StrFromC(p->name));
|
101 | break;
|
102 | case ActionType_c::SetNamedOption: {
|
103 | auto a = Alloc<args::SetNamedOption>(false);
|
104 | if (p->strs) {
|
105 | _CreateStrList(p->strs, a->names);
|
106 | }
|
107 | action = a;
|
108 | } break;
|
109 | case ActionType_c::SetNamedOption_shopt: {
|
110 | auto a = Alloc<args::SetNamedOption>(true);
|
111 | if (p->strs) {
|
112 | _CreateStrList(p->strs, a->names);
|
113 | }
|
114 | action = a;
|
115 | } break;
|
116 | case ActionType_c::SetAction:
|
117 | action = Alloc<args::SetAction>(StrFromC(p->name));
|
118 | break;
|
119 | case ActionType_c::SetNamedAction: {
|
120 | auto a = Alloc<args::SetNamedAction>();
|
121 | if (p->strs) {
|
122 | _CreateStrList(p->strs, a->names);
|
123 | }
|
124 | action = a;
|
125 | } break;
|
126 | }
|
127 |
|
128 | if (action) {
|
129 | out->set(StrFromC(p->key), action);
|
130 | }
|
131 | ++i;
|
132 | }
|
133 | }
|
134 |
|
135 | // Convenience function
|
136 | template <typename K, typename V>
|
137 | Dict<K, V>* NewDict() {
|
138 | return Alloc<Dict<K, V>>();
|
139 | }
|
140 |
|
141 | // "Inflate" the static C data into a heap-allocated ASDL data structure.
|
142 | //
|
143 | // TODO: Make a GLOBAL CACHE? It could be shared between subinterpreters even?
|
144 | flag_spec::_FlagSpec* CreateSpec(FlagSpec_c* in) {
|
145 | auto out = Alloc<flag_spec::_FlagSpec>();
|
146 | out->arity0 = NewList<BigStr*>();
|
147 | out->arity1 = NewDict<BigStr*, args::_Action*>();
|
148 | out->actions_long = NewDict<BigStr*, args::_Action*>();
|
149 | out->plus_flags = NewList<BigStr*>();
|
150 | out->defaults = NewDict<BigStr*, value_asdl::value_t*>();
|
151 |
|
152 | if (in->arity0) {
|
153 | _CreateStrList(in->arity0, out->arity0);
|
154 | }
|
155 | if (in->arity1) {
|
156 | _CreateActions(in->arity1, out->arity1);
|
157 | }
|
158 | if (in->actions_long) {
|
159 | _CreateActions(in->actions_long, out->actions_long);
|
160 | }
|
161 | if (in->plus_flags) {
|
162 | _CreateStrList(in->plus_flags, out->plus_flags);
|
163 | }
|
164 | if (in->defaults) {
|
165 | _CreateDefaults(in->defaults, out->defaults);
|
166 | }
|
167 | return out;
|
168 | }
|
169 |
|
170 | flag_spec::_FlagSpecAndMore* CreateSpec2(FlagSpecAndMore_c* in) {
|
171 | auto out = Alloc<flag_spec::_FlagSpecAndMore>();
|
172 | out->actions_short = NewDict<BigStr*, args::_Action*>();
|
173 | out->actions_long = NewDict<BigStr*, args::_Action*>();
|
174 | out->plus_flags = NewList<BigStr*>();
|
175 | out->defaults = NewDict<BigStr*, value_asdl::value_t*>();
|
176 |
|
177 | if (in->actions_short) {
|
178 | _CreateActions(in->actions_short, out->actions_short);
|
179 | }
|
180 | if (in->actions_long) {
|
181 | _CreateActions(in->actions_long, out->actions_long);
|
182 | }
|
183 | if (in->plus_flags) {
|
184 | _CreateStrList(in->plus_flags, out->plus_flags);
|
185 | }
|
186 | if (in->defaults) {
|
187 | _CreateDefaults(in->defaults, out->defaults);
|
188 | }
|
189 | return out;
|
190 | }
|
191 |
|
192 | using arg_types::kFlagSpecs;
|
193 | using arg_types::kFlagSpecsAndMore;
|
194 |
|
195 | flag_spec::_FlagSpec* LookupFlagSpec(BigStr* spec_name) {
|
196 | int i = 0;
|
197 | while (true) {
|
198 | const char* name = kFlagSpecs[i].name;
|
199 | if (name == nullptr) {
|
200 | break;
|
201 | }
|
202 | if (str_equals0(name, spec_name)) {
|
203 | // log("%s found", spec_name->data_);
|
204 | return CreateSpec(&kFlagSpecs[i]);
|
205 | }
|
206 |
|
207 | i++;
|
208 | }
|
209 | // log("%s not found", spec_name->data_);
|
210 | return nullptr;
|
211 | }
|
212 |
|
213 | flag_spec::_FlagSpecAndMore* LookupFlagSpec2(BigStr* spec_name) {
|
214 | int i = 0;
|
215 | while (true) {
|
216 | const char* name = kFlagSpecsAndMore[i].name;
|
217 | if (name == nullptr) {
|
218 | break;
|
219 | }
|
220 | if (str_equals0(name, spec_name)) {
|
221 | // log("%s found", spec_name->data_);
|
222 | return CreateSpec2(&kFlagSpecsAndMore[i]);
|
223 | }
|
224 |
|
225 | i++;
|
226 | }
|
227 | // log("%s not found", spec_name->data_);
|
228 | return nullptr;
|
229 | }
|
230 |
|
231 | } // namespace flag_util
|