root/trunk/orca/bytecode.c

Revision 54, 9.5 kB (checked in by krobillard, 3 years ago)

Now using orDecimal() & orInt() where appropriate.

Line 
1 /*============================================================================
2     ORCA Interpreter
3     Copyright (C) 2005-2006  Karl Robillard
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Lesser General Public
7     License as published by the Free Software Foundation; either
8     version 2.1 of the License, or (at your option) any later version.
9
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Lesser General Public License for more details.
14
15     You should have received a copy of the GNU Lesser General Public
16     License along with this library; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 ===========================================================================*/
19
20
21 #include "ovalue.h"
22 #include "os.h"
23
24
25 /*
26   TODO:
27     * Save formatting (OR_FLAG_EOL / OR_FLAG_BEOL)?
28     * Make word/string table (would make boot.r much smaller)?
29 */
30
31
32 #ifdef OR_CONFIG_BYTECODE
33
34 #define BIG_VALUE       0x80
35
36 #define RESERVE(n) \
37     orArrayReserve( bin, 1, bin->used + n ); \
38     cp = bin->byteArray + bin->used; \
39     bin->used += n
40
41
42 /*
43    Appends byte-code representation of value to binary.
44 */
45 void orCompileByteCodes( OBinary* bin, const OValue* val )
46 {
47     uint8_t* cp;
48
49     switch( val->type )
50     {
51         case OT_WORD:
52         case OT_LITWORD:
53         case OT_SETWORD:
54         case OT_GETWORD:
55         case OT_REFINEMENT:
56         {
57             int pos;
58             int atom;
59
60             atom = (val->type == OT_REFINEMENT) ? val->index : val->word.atom;
61             pos = bin->used;
62
63             orArrayReserve( bin, 1, bin->used + 2 );
64             bin->used += 2;
65
66             orAtomStr( atom, bin );
67
68             // LIMIT: Word names can never be more than 255 characters.
69             cp = bin->byteArray + pos;
70             *cp++ = val->type;
71             *cp   = bin->used - pos - 2;
72         }
73             break;
74
75         case OT_INTEGER:
76         {
77             int i = orInt(val);
78             if( i > 255 )
79             {
80                 RESERVE( 5 );
81                 *cp++ = BIG_VALUE | val->type;
82                 *cp++ = (i >> 24) & 0xff;
83                 *cp++ = (i >> 16) & 0xff;
84                 *cp++ = (i >>  8) & 0xff;
85             }
86             else
87             {
88                 RESERVE( 2 );
89                 *cp++ = val->type;
90             }
91             *cp = i & 0xff;
92         }
93             break;
94
95         case OT_DECIMAL:
96         {
97             const uint8_t* end;
98             uint64_t li;
99             int shift = 56;
100
101             RESERVE( 9 );
102             *cp++ = val->type;
103
104             end = cp + 8;
105             li = *((uint64_t*) &orDecimal(val));
106             while( cp != end )
107             {
108                 *cp++ = (uint8_t) (li >> shift) & 0xff;
109                 shift -= 8;
110             }
111         }
112             break;
113
114         case OT_CHAR:
115         case OT_LOGIC:
116         case OT_DATATYPE:
117             RESERVE( 2 );
118             *cp++ = val->type;
119             *cp   = orInt(val) & 0xff;
120             break;
121
122         case OT_TUPLE:
123         {
124             int len = val->argc + 2;
125             RESERVE( len );
126             len -= 2;
127             *cp++ = val->type;
128             *cp++ = len;
129             if( len )
130                 memCpy( cp, val->tuple, len );
131         }
132             break;
133
134         //case OT_TIME:
135
136         case OT_BLOCK:
137         case OT_PAREN:
138         case OT_PATH:
139         case OT_LITPATH:
140         case OT_SETPATH:
141         {
142             OBlock* blk = orBLOCKS + val->index;
143             OValue* it  = blk->values + val->series.it;
144             OValue* end = blk->values + blk->used;
145             int len = end - it;
146
147             if( len > 255 )
148             {
149                 RESERVE( 5 );
150                 *cp++ = BIG_VALUE | val->type;
151                 *cp++ = (len >> 24) & 0xff;
152                 *cp++ = (len >> 16) & 0xff;
153                 *cp++ = (len >>  8) & 0xff;
154             }
155             else
156             {
157                 RESERVE( 2 );
158                 *cp++ = val->type;
159             }
160             *cp = len & 0xff;
161
162             while( it != end )
163             {
164                 orCompileByteCodes( bin, it );
165                 ++it;
166             }
167         }
168             break;
169
170         case OT_STRING:
171         case OT_ISSUE:
172         case OT_TAG:
173         case OT_FILE:
174         case OT_BINARY:
175         {
176             OString* str = orSTRINGS + val->index;
177             int len = str->used - val->series.it;
178
179             if( len > 255 )
180             {
181                 len += 5;
182                 RESERVE( len );
183                 len -= 5;
184                 *cp++ = BIG_VALUE | val->type;
185                 *cp++ = (len >> 24) & 0xff;
186                 *cp++ = (len >> 16) & 0xff;
187                 *cp++ = (len >>  8) & 0xff;
188             }
189             else
190             {
191                 len += 2;
192                 RESERVE( len );
193                 len -= 2;
194                 *cp++ = val->type;
195             }
196             *cp++ = len & 0xff;
197
198             memCpy( cp, str->charArray + val->series.it, len );
199         }
200             break;
201
202         default:
203             RESERVE( 1 );
204             *cp = val->type;
205             break;
206     }
207 }
208
209
210 /*
211    Returns value length of block.
212    Sets lenp to value length and codep to start of value byte-code.
213 */
214 OIndex orByteCodeBlock( const uint8_t** codep, OIndex* lenp )
215 {
216     int type;
217     int big;
218     OIndex len = 0;
219     const uint8_t* cp = *codep;
220
221     type = *cp++;
222     big = type & BIG_VALUE;
223     if( big )
224         type &= ~BIG_VALUE;
225
226     if( type == OT_BLOCK )
227     {
228         if( big )
229         {
230             len  = *cp++ << 24;
231             len += *cp++ << 16;
232             len += *cp++ <<  8;
233             len += *cp++;
234         }
235         else
236         {
237             len = *cp++;
238         }
239
240         *codep = cp;
241     }
242
243     *lenp = len;
244     return len;
245 }
246
247
248 /*
249    Appends value representation of byte-codes to block.
250 */
251 const uint8_t* orRevaluateByteCodes( const uint8_t* cp, int valueCount,
252                                      OBlock* blk )
253 {
254     OIndex blkN;
255     int type;
256     int len;
257     int big;
258
259     blkN = orBlockN( blk );
260
261     while( valueCount-- )
262     {
263         type = *cp++;
264
265         big = type & BIG_VALUE;
266         if( big )
267             type &= ~BIG_VALUE;
268
269         switch( type )
270         {
271             case OT_WORD:
272             case OT_LITWORD:
273             case OT_SETWORD:
274             case OT_GETWORD:
275             {
276                 len = *cp++;
277                 orAppendWord( blk, type, (const char*) cp, len );
278                 cp += len;
279             }
280                 break;
281
282             case OT_REFINEMENT:
283             {
284                 int n;
285                 len = *cp++;
286                 n = orInternAtom( (const char*) cp, len );
287                 cp += len;
288                 orAppendValue( blk, type, n );
289             }
290                 break;
291
292             case OT_INTEGER:
293                 if( big )
294                 {
295                     len  = *cp++ << 24;
296                     len += *cp++ << 16;
297                     len += *cp++ <<  8;
298                     len += *cp++;
299                 }
300                 else
301                 {
302                     len = *cp++;
303                 }
304                 orAppendValue( blk, type, len );
305                 break;
306
307             case OT_DECIMAL:
308             {
309                 const uint8_t* end;
310                 double n;
311                 union {
312                     uint64_t i;
313                     double   d;
314                 } num;
315
316                 num.i = *cp++;
317                 end = cp + 7;
318                 while( cp != end )
319                 {
320                     num.i <<= 8;
321                     num.i += *cp++;
322                 }
323                 n = num.d;
324                 orAppendDecimal( blk, n );
325             }
326                 break;
327
328             case OT_CHAR:
329             case OT_LOGIC:
330             case OT_DATATYPE:
331                 orAppendValue( blk, type, *cp++ );
332                 break;
333
334             case OT_TUPLE:
335                 len = *cp++;
336                 orAppendTuple( blk, cp, len );
337                 cp += len;
338                 break;
339
340             case OT_BLOCK:
341             case OT_PAREN:
342             case OT_PATH:
343             case OT_LITPATH:
344             case OT_SETPATH:
345             {
346                 if( big )
347                 {
348                     len  = *cp++ << 24;
349                     len += *cp++ << 16;
350                     len += *cp++ <<  8;
351                     len += *cp++;
352                 }
353                 else
354                 {
355                     len = *cp++;
356                 }
357
358                 blk = orMakeBlock( len );
359                 orAppendValue( orBLOCKS + blkN, type, blk - orBLOCKS );
360                 cp = orRevaluateByteCodes( cp, len, blk );
361
362                 // Re-acquire blk.
363                 blk = orBLOCKS + blkN;
364             }
365                 break;
366
367             case OT_STRING:
368             case OT_ISSUE:
369             case OT_TAG:
370             case OT_FILE:
371             case OT_BINARY:
372                 if( big )
373                 {
374                     len  = *cp++ << 24;
375                     len += *cp++ << 16;
376                     len += *cp++ <<  8;
377                     len += *cp++;
378                 }
379                 else
380                 {
381                     len = *cp++;
382                 }
383                 orAppendValue( blk, type, orMakeCString((const char*) cp, len) );
384                 cp += len;
385                 break;
386
387             case OT_NONE:
388                 orAppendNone( blk );
389                 break;
390
391             default:
392                 break;
393         }
394     }
395
396     return cp;
397 }
398
399 #endif
400
401
402 /*EOF*/
Note: See TracBrowser for help on using the browser.