Ticket #1644: pasmserializer.pmc

File pasmserializer.pmc, 6.2 KB (added by plobsing, 4 years ago)

Serializer POC

Line 
1/*
2Copyright (C) 2010, Parrot Foundation.
3$Id$
4
5=head1
6
7src/pmc/pasmserializer - PASM Object Serializer
8
9=head1 DESCRIPTION
10
11Freezes and thaws PMCs using a text format suitable for use in PASM.
12
13=head2 Vtables
14
15=over 4
16
17=cut
18
19*/
20
21/* HEADERIZER HFILE: none */
22
23pmclass PASMSerializer auto_attrs {
24    ATTR PMC     *buffer;
25    ATTR PMC     *seen;
26    ATTR PMC     *todo;
27    ATTR UINTVAL  id;
28    ATTR INTVAL   action;
29
30/*
31
32=item C<void init()>
33
34Initialize the serializer.
35
36=cut
37
38*/
39
40    VTABLE void init() {
41        PARROT_PASMSERIALIZER(SELF)->buffer = PMCNULL;
42        PARROT_PASMSERIALIZER(SELF)->todo   = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
43        PARROT_PASMSERIALIZER(SELF)->seen   = PMCNULL;
44        PARROT_PASMSERIALIZER(SELF)->id     = 0;
45
46        PObj_custom_mark_SET(SELF);
47    }
48
49/*
50
51=item C<void mark()>
52
53Mark the PMC as alive.
54
55=cut
56
57*/
58
59    VTABLE void mark() {
60        Parrot_gc_mark_PMC_alive(INTERP, PARROT_PASMSERIALIZER(SELF)->buffer);
61        Parrot_gc_mark_PMC_alive(INTERP, PARROT_PASMSERIALIZER(SELF)->todo);
62        Parrot_gc_mark_PMC_alive(INTERP, PARROT_PASMSERIALIZER(SELF)->seen);
63    }
64
65/*
66
67=item C<PMC *get_iter()>
68
69Get the C<todo> list for this freeze/thaw for iterating over.
70
71=cut
72
73*/
74
75    VTABLE PMC *get_iter() {
76        return PARROT_PASMSERIALIZER(SELF)->todo;
77    }
78
79/*
80
81=item C<INTVAL get_integer()>
82
83Get the flags describing this visit action
84
85=cut
86
87*/
88
89    VTABLE INTVAL get_integer() {
90        return PARROT_PASMSERIALIZER(SELF)->action;
91    }
92
93/*
94
95=item C<void push_integer(INTVAL v)>
96
97=item C<void push_float(FLOATVAL v)>
98
99=item C<void push_string(STRING *v)>
100
101=item C<void push_pmc(PMC *v)>
102
103Push data item C<v> onto the end of the image being frozen.
104
105=cut
106
107*/
108
109    VTABLE void push_integer(INTVAL v) {
110        PMC *buf = PARROT_PASMSERIALIZER(SELF)->buffer;
111        VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, " "));
112        VTABLE_push_string(INTERP, buf, Parrot_str_from_int(INTERP, v));
113        VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, " "));
114    }
115
116    VTABLE void push_float(FLOATVAL v) {
117        PMC *buf = PARROT_PASMSERIALIZER(SELF)->buffer;
118        VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, " "));
119        VTABLE_push_string(INTERP, buf, Parrot_str_from_num(INTERP, v));
120        VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, " "));
121    }
122
123    VTABLE void push_string(STRING *v) {
124        PMC *buf = PARROT_PASMSERIALIZER(SELF)->buffer;
125        VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, " "));
126        if (STRING_IS_NULL(v)) {
127            VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, "STRINGNULL"));
128        }
129        else {
130            VTABLE_push_string(INTERP, buf,
131                    Parrot_encoding_name(INTERP, Parrot_encoding_number_of_str(INTERP, v)));
132            VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, ":"));
133            VTABLE_push_string(INTERP, buf,
134                    Parrot_charset_name(INTERP, Parrot_charset_number_of_str(INTERP, v)));
135            VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, ":\""));
136            VTABLE_push_string(INTERP, buf, Parrot_str_escape(INTERP, v));
137            VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, "\""));
138        }
139        VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, " "));
140    }
141
142    VTABLE void push_pmc(PMC *v) {
143        PMC    *buf       = PARROT_PASMSERIALIZER(SELF)->buffer;
144        PMC    *seen      = PARROT_PASMSERIALIZER(SELF)->seen;
145        INTVAL  id;
146        INTVAL  was_seen;
147
148        VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, " "));
149
150        if (PMC_IS_NULL(v)) {
151            id = 0;
152            was_seen = 1;
153        }
154        else {
155            was_seen = VTABLE_exists_keyed(INTERP, seen, v);
156            if (was_seen)
157                id = VTABLE_get_integer_keyed(INTERP, seen, v);
158            else
159                id = ++PARROT_PASMSERIALIZER(SELF)->id;
160        }
161
162        VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, "$"));
163        VTABLE_push_string(INTERP, buf, Parrot_str_from_int(INTERP, id));
164
165        if (!was_seen) {
166            VTABLE_set_integer_keyed(INTERP, seen, v, id);
167            VTABLE_push_pmc(INTERP, PARROT_PASMSERIALIZER(SELF)->todo, v);
168
169            VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, ":"));
170            VTABLE_push_string(INTERP, buf, VTABLE_name(INTERP, v));
171
172            VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, "{"));
173            VTABLE_freeze(INTERP, v, SELF);
174            VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, "}"));
175        }
176
177        VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, " "));
178    }
179
180/*
181
182=item C<STRING *get_string()>
183
184Get the serialized image as a string (after freezing).
185
186=cut
187
188*/
189
190    VTABLE STRING *get_string() {
191        return VTABLE_get_string(INTERP, PARROT_PASMSERIALIZER(SELF)->buffer);
192    }
193
194/*
195
196=item C<void set_pmc(PMC *p)>
197
198Freeze the PMC C<p> into the buffer.
199
200=cut
201
202*/
203
204    VTABLE void set_pmc(PMC *p) {
205        PARROT_PASMSERIALIZER(SELF)->action = VISIT_FREEZE_NORMAL;
206        PARROT_PASMSERIALIZER(SELF)->buffer = Parrot_pmc_new(INTERP, enum_class_StringBuilder);
207        PARROT_PASMSERIALIZER(SELF)->seen   = Parrot_pmc_new(INTERP, enum_class_Hash);
208        VTABLE_set_pointer(INTERP, PARROT_PASMSERIALIZER(SELF)->seen,
209                parrot_new_intval_hash(INTERP));
210        SELF.push_pmc(p);
211
212        // Parrot_visit_loop_visit(INTERP, SELF);
213        {
214            INTVAL i;
215            PMC *buf  = PARROT_PASMSERIALIZER(SELF)->buffer;
216            PMC *todo = VTABLE_get_iter(INTERP, SELF);
217            for (i = 0; i < VTABLE_elements(INTERP, todo); i++) {
218                PMC *current = VTABLE_get_pmc_keyed_int(INTERP, todo, i);
219
220                VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, "\n$"));
221                VTABLE_push_string(INTERP, buf, Parrot_str_from_int(INTERP, i + 1));
222                VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, ":["));
223
224                VTABLE_visit(INTERP, current, SELF);
225                VISIT_PMC(INTERP, SELF, PMC_metadata(current));
226
227                VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, "]"));
228            }
229        }
230    }
231}
232
233/*
234
235=back
236
237=cut
238
239*/
240
241/*
242 * Local variables:
243 *   c-file-style: "parrot"
244 * End:
245 * vim: expandtab shiftwidth=4:
246 */