| 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
|