update pet to version 0.11.5
[ppn.git] / include / isa / yaml.h
bloba285301790c014cbf653517186402d8f3677c392
1 #ifndef ISA_YAML_H
2 #define ISA_YAML_H
4 #include <map>
5 #include <string>
6 #include <typeinfo>
7 #include <vector>
8 #define partition algorithm_partition
9 #include <algorithm>
10 #undef partition
12 #include <assert.h>
13 #include <stdio.h>
14 #include <string.h>
16 using std::type_info;
17 using std::map;
18 using std::pair;
19 using std::string;
21 extern "C" {
22 #include <syck.h>
23 #include <isa/yll.h>
26 #define YAML_PTR_FIELD(sd, class, name, type) do { \
27 assert(typeid(&class::name) == typeid(type *class::*)); \
28 sd.m[ #name ] = new ptr_field((ptr_field_t) &class::name, &typeid(type)); \
29 } while(0)
30 #define YAML_INT_FIELD(sd, class, name) \
31 sd.m[ #name ] = new int_field(static_cast<int_field_t>(&class::name), &typeid(int));
32 #define YAML_ENUM_FIELD(sd, class, name, names) \
33 sd.m[ #name ] = new_enum_field(&class::name, \
34 names, sizeof(names)/sizeof(*names));
35 #define YAML_SEQ_FIELD(sd, class, name, type) \
36 sd.m[ #name ] = new seq_field<type> \
37 ((seq_field<type>::seq_field_t) &class::name);
39 namespace yaml
42 struct at_init {
43 at_init(void (*f)(void)) { f(); }
46 class serialize;
47 class anchor_map;
48 typedef serialize* serialize_p;
50 struct description {
51 serialize *(*create)(void *user);
52 serialize_p (*convert) (anchor_map *, serialize *, const type_info *);
53 const type_info *type;
56 struct ptr_field;
57 struct int_field;
58 template <class el> struct seq_field;
60 class replacer_base {
61 protected:
62 friend bool operator==(const replacer_base& a, const replacer_base& b);
63 serialize*& ref;
64 public:
65 replacer_base(serialize*& r) : ref(r) {}
66 virtual void with(serialize *replacement) {
67 ref = replacement;
71 inline bool operator==(const replacer_base& a, const replacer_base& b)
73 return &a.ref == &b.ref;
76 template <class el>
77 class replacer : public replacer_base {
78 public:
79 replacer(el*& r) : replacer_base((serialize *&)r) {}
80 virtual void with(serialize *replacement) {
81 ref = dynamic_cast<el*>(replacement);
85 typedef map<serialize *, unsigned> refset;
87 struct emitter {
88 YllEmitter *e;
89 refset refs;
90 map<serialize *, SYMID> anchors;
91 emitter() { e = yll_new_emitter(); }
92 ~emitter() { yll_free_emitter(e); }
93 bool anchor_handled(serialize *s);
96 struct description_map {
97 map<string, description *> *desc;
99 description_map() {
100 desc = NULL;
102 ~description_map() {
103 if (desc)
104 delete desc;
108 class serialize {
109 static void syck_output_handler(YllEmitter *p, char *s, long len);
110 static SYMID syck_handler(SyckParser *p, SyckNode *n);
111 static SyckNode * bad_anchor_handler(SyckParser *, char *);
113 protected:
114 friend struct ptr_field;
115 friend struct int_field;
116 template <class el> friend struct seq_field;
118 static map<string, description*>& s_desc() {
119 static description_map desc;
120 if (!desc.desc)
121 desc.desc = new map<string, description*>;
122 return *desc.desc;
124 static map<const type_info *, description*>& t_desc() {
125 static map<const type_info *, description*> *desc = 0;
126 if (!desc)
127 desc = new map<const type_info *, description*>;
128 return *desc;
131 static void register_type(const char *, const type_info *, description *);
133 public:
134 static serialize *Load(SyckParser *parser, const type_info *type,
135 void *user);
136 static serialize *Load(char *str, const type_info *type, void *user);
137 static serialize *Load(FILE *fp, const type_info *type, void *user);
139 void Dump(FILE *out = stdout);
140 virtual void Dump(emitter& e) {
141 if (!e.anchor_handled(this))
142 dump(e);
144 virtual void dump(emitter& e) = 0;
146 virtual void collect_references(refset& refs);
148 virtual void free();
150 virtual void init(SyckParser *p, SyckNode *n) = 0;
152 virtual ~serialize() {
157 typedef pair<SYMID, std::vector<replacer_base *> > rep_pair;
159 class anchor_map {
160 map<serialize *, rep_pair > anchors;
161 SyckParser *p;
163 public:
164 void *user;
166 void add(serialize* s, SYMID id) {
167 anchors[s] = rep_pair(id, std::vector<replacer_base *>());
169 void replace(serialize *s, replacer_base *orig, replacer_base *replace) {
170 bool found = false;
171 for (int i = 0; i < anchors[s].second.size(); ++i) {
172 replacer_base * r = anchors[s].second[i];
173 if (*r == *orig) {
174 delete r;
175 anchors[s].second[i] = replace;
176 found = true;
179 delete orig;
180 if (!found)
181 this->replace(s, replace);
183 void replace(serialize *s, replacer_base *replace) {
184 anchors[s].second.push_back(replace);
186 bool is_anchor(serialize *s) { return anchors.find(s) != anchors.end(); }
187 serialize * replace(SYMID id, serialize *replacement);
188 serialize * replace(serialize * orig, serialize *replacement) {
189 return replace(anchors[orig].first, replacement);
191 ~anchor_map();
192 anchor_map(SyckParser *_p, void *user) : p(_p), user(user) {}
195 class bad_anchor : public serialize {
196 public:
197 void init(SyckParser *p, SyckNode *n) {};
198 void dump(emitter& e) { assert(0); }
201 class str : public serialize {
202 str() {}
203 public:
204 string s;
205 str(string _s) : s(_s) {}
206 static void register_type();
207 static serialize *create(void *user);
208 void init(SyckParser *p, SyckNode *n);
209 void dump(emitter& e) { yll_emitter_write_string(e.e, s.c_str()); }
212 class integer : public serialize {
213 static serialize_p convert (anchor_map *, serialize *, const type_info *);
215 integer() {}
216 public:
217 int v;
218 integer(int _v) : v(_v) {}
219 static void register_type();
220 static serialize *create(void *user);
221 void init(SyckParser *p, SyckNode *n);
222 void dump(emitter& e) { yll_emitter_write_int(e.e, v); }
225 typedef map<string, serialize *> sermap;
227 typedef map<string,serialize_p>::mapped_type mapped_type;
229 class dict : public serialize {
230 protected:
232 public:
233 map<string,serialize_p> *d;
235 //static void register_type();
236 static serialize_p create();
237 void init(SyckParser *p, SyckNode *n);
238 void dump(emitter& e);
240 void collect_references(refset& refs);
242 mapped_type& operator[](string s) { return (*d)[s]; }
244 ~dict() {
245 if (d)
246 delete d;
250 template <class el>
251 class seq : public serialize {
252 public:
253 std::vector<el *> v;
255 //static void register_type();
256 static serialize_p create() { return new seq<el>; }
258 void init(SyckParser *p, SyckNode *n) {
259 anchor_map *anchors = (anchor_map *) p->bonus;
260 for (int i = 0; i < n->data.list->idx; i++) {
261 el *val;
262 SYMID oid = syck_seq_read(n, i);
263 syck_lookup_sym( p, oid, (char **)&val );
264 v.push_back(val);
266 // In a second iteration, since we wouldn't want the
267 // memory locations to change for the replacer
268 for (int i = 0; i < n->data.list->idx; i++) {
269 if (anchors->is_anchor(v[i])) {
270 anchors->replace(v[i], new replacer<el>(v[i]));
275 void collect_references(refset& refs) {
276 serialize::collect_references(refs);
277 for (int i = 0; i < v.size(); ++i) {
278 el *e = v[i];
279 if (refs.find(e) == refs.end())
280 e->collect_references(refs);
281 else
282 ++refs[e];
286 void dump(emitter& e) {
287 yll_emitter_start_seq(e.e);
288 for (int i = 0; i < v.size(); ++i) {
289 v[i]->Dump(e);
291 yll_emitter_end_seq(e.e);
294 el*& operator[](int i) { return v[i]; }
295 el* const & operator[](int i) const { return v[i]; }
296 size_t size() const { return v.size(); }
297 void push_back(el *e) { v.push_back(e); }
298 void resize(int n) { v.resize(n); }
299 void erase(el *e) { if (find(v.begin(), v.end(), e) != v.end())
300 v.erase(find(v.begin(), v.end(), e)); }
302 ~seq() {
306 template <>
307 class seq<int> : public serialize {
308 public:
309 std::vector<int> v;
311 //static void register_type();
312 static serialize_p create() { return new seq<int>; }
314 void init(SyckParser *p, SyckNode *n) {
315 for (int i = 0; i < n->data.list->idx; i++) {
316 str* val;
317 SYMID oid = syck_seq_read(n, i);
318 syck_lookup_sym( p, oid, (char **)&val );
319 v.push_back(atoi(val->s.c_str()));
323 void collect_references(refset& refs) {
324 serialize::collect_references(refs);
327 void dump(emitter& e) { assert(0); }
329 int& operator[](int i) { return v[i]; }
330 int const & operator[](int i) const { return v[i]; }
331 size_t size() const { return v.size(); }
332 void push_back(int e) { v.push_back(e); }
333 void resize(int n) { v.resize(n); }
335 ~seq() {
339 class structure;
340 typedef serialize * structure::* ptr_field_t;
341 typedef int structure::* int_field_t;
343 struct field {
344 const type_info *type;
345 field() {};
346 field(const type_info *t) : type(t) {};
347 virtual bool set(anchor_map *am, structure *, serialize *&) { assert(0); }
348 virtual void collect(structure * s, refset& refs) { assert(0); }
349 virtual void dump(structure * s, emitter& refs) { assert(0); }
350 virtual bool is_empty(structure *) { return false; }
353 struct ptr_field : field {
354 serialize * structure::* pos;
355 ptr_field(ptr_field_t p, const type_info *t) : pos(p), field(t) {};
356 bool set(anchor_map *am, structure *, serialize *&);
357 void collect(structure * s, refset& refs);
358 void dump(structure * s, emitter& refs);
359 bool is_empty(structure * s) { return !(s->*pos); }
362 struct int_field : field {
363 int structure::* pos;
364 int_field(int_field_t p, const type_info *t) : pos(p), field(t) {};
365 bool set(anchor_map *am, structure *, serialize *&);
366 void collect(structure * s, refset& refs);
367 void dump(structure * s, emitter& refs);
370 template <typename T, class C>
371 struct enum_field : field {
372 T C::* pos;
373 const char **names;
374 const int size;
375 enum_field(T C::* p, const char **names,
376 const int size) : names(names), size(size), pos(p), field(&typeid(T)) {};
377 bool set(anchor_map *am, structure *, serialize *&);
378 void collect(structure * s, refset& refs) { }
379 void dump(structure * s, emitter& refs);
382 template <typename T, class C>
383 bool enum_field<T,C>::set(anchor_map *am, structure * sc, serialize *& el)
385 str *s = dynamic_cast<str *>(el);
386 C *c = dynamic_cast<C *>(sc);
387 if (!s)
388 return false;
390 if (!strcmp(s->s.c_str(), "~")) {
391 c->*pos = static_cast<T>(-1);
392 delete el;
393 return true;
396 for (int i = 0; i < size; ++i)
397 if (!strcmp(s->s.c_str(), names[i])) {
398 c->*pos = static_cast<T>(i);
399 delete el;
400 return true;
403 return false;
406 template <typename T, class C>
407 void enum_field<T,C>::dump(structure * sc, emitter& e)
409 C *c = dynamic_cast<C *>(sc);
410 if (c->*pos >= 0 && c->*pos < size)
411 yll_emitter_write_string(e.e, names[c->*pos]);
412 else
413 yll_emitter_write_null(e.e);
416 template <typename T, class C>
417 inline field *new_enum_field(T C::* p, const char **names, const int size)
419 return new enum_field<T,C>(p, names, size);
422 template <class el>
423 struct seq_field : field {
424 typedef seq<el> structure::* seq_field_t;
426 seq<el> structure::* pos;
427 seq_field(seq_field_t p) : pos(p), field(&typeid(el)) {};
428 bool set(anchor_map *am, structure * c, serialize * &s) {
429 map<const type_info *, description*>& desc = serialize::t_desc();
430 seq<serialize> * sq = dynamic_cast<seq<serialize>*>(s);
431 if (!sq)
432 return false;
433 (c->*pos).v = std::vector<el *>(sq->size());
434 for (int i = 0; i < sq->size(); ++i) {
435 serialize * e = sq->v[i];
436 if (typeid(el) != typeid(*e))
437 e = desc[&typeid(el)]->convert(am, e, type);
439 (c->*pos).v[i] = dynamic_cast<el *>(e);
441 if (am->is_anchor(e)) {
442 am->replace(e, new replacer<serialize>(sq->v[i]),
443 new replacer<el>((c->*pos).v[i]));
446 delete sq;
447 return true;
449 void collect(structure * c, refset& refs) {
450 std::vector<el *> & v = (c->*pos).v;
451 for (int i = 0; i < v.size(); ++i) {
452 serialize *e = v[i];
453 if (!e)
454 continue;
455 if (refs.find(e) == refs.end())
456 e->collect_references(refs);
457 else
458 ++refs[e];
461 void dump(structure * s, emitter& emit) {
462 std::vector<el *> & v = (s->*pos).v;
463 yll_emitter_start_seq(emit.e);
464 for (int i = 0; i < v.size(); ++i) {
465 serialize *e = v[i];
466 if (e)
467 e->Dump(emit);
468 else
469 yll_emitter_write_null(emit.e);
471 yll_emitter_end_seq(emit.e);
473 bool is_empty(structure * s) { return (s->*pos).v.size() == 0; }
476 template <>
477 struct seq_field<int> : field {
478 typedef seq<int> structure::* seq_field_t;
480 seq<int> structure::* pos;
481 seq_field(seq_field_t p) : pos(p), field(&typeid(int)) {};
482 bool set(anchor_map *am, structure * c, serialize * &s) {
483 map<const type_info *, description*>& desc = serialize::t_desc();
484 seq<serialize> * sq = dynamic_cast<seq<serialize>*>(s);
485 if (!sq)
486 return false;
487 (c->*pos).v = std::vector<int>(sq->size());
488 for (int i = 0; i < sq->size(); ++i) {
489 serialize * e = sq->v[i];
490 if (typeid(str) != typeid(*e))
491 e = desc[&typeid(str)]->convert(am, e, type);
492 str * s = dynamic_cast<str *>(e);
494 (c->*pos).v[i] = atoi(s->s.c_str());
495 delete s;
497 delete sq;
498 return true;
500 void collect(structure * c, refset& refs) {
502 void dump(structure * s, emitter& emit) {
503 std::vector<int> & v = (s->*pos).v;
504 yll_emitter_set_options(emit.e, YLL_INLINE_SEQ);
505 yll_emitter_start_seq(emit.e);
506 for (int i = 0; i < v.size(); ++i) {
507 yll_emitter_write_int(emit.e, v[i]);
509 yll_emitter_end_seq(emit.e);
513 typedef map<string, field *> fieldmap;
515 struct struct_description {
516 description d;
517 fieldmap m;
518 ~struct_description() {
519 fieldmap::iterator j;
520 for (j = m.begin(); j != m.end(); ++j)
521 delete j->second;
525 class structure : public serialize {
527 public:
528 map<string,serialize_p> *d;
530 static void register_type(const char *, const type_info *, description *);
531 static serialize_p convert (anchor_map *, serialize *, const type_info *);
533 void collect_references(refset& refs);
534 void init(SyckParser *p, SyckNode *n);
535 void dump(emitter& e);
536 virtual void fill_fields(anchor_map *);
538 structure() { d = NULL; }
539 ~structure() { if (d) delete d; }
542 serialize *Load(char *str, const type_info *type = NULL, void *user = NULL);
543 serialize *Load(FILE *fp, const type_info *type = NULL, void *user = NULL);
544 template <class T>
545 T *Load(char *str, void *user = NULL) {
546 return dynamic_cast<T*>(Load(str, &typeid(T), user));
548 template <class T>
549 T *Load(FILE *fp, void *user = NULL) {
550 return dynamic_cast<T*>(Load(fp, &typeid(T), user));
555 #endif