Welcome, Guest! Log In | Create Account

root/trunk/orca/bytecode.c

Revision 54, 9.5 KB (checked in by krobillard, 4 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*/
45void 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*/
214OIndex 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*/
251const 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.