root/trunk/orca/ovalue.c

Revision 298, 101.1 kB (checked in by krobillard, 2 years ago)

Orca - 'do no longer clobbers thrown error.

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 "os.h"
22 #include "ovalue.h"
23 #include "internal.h"
24 #include "orca_atoms.h"
25
26 #ifdef OR_CONFIG_MATH3D
27 #include <math3d.h>
28 #endif
29
30
31 //#define MAKE_ATOM_HEADER    1
32
33
34 static const char* _datatypes[] =
35 {
36     "unset",
37     "none",
38     "word",
39     "lit-word",
40     "set-word",
41     "get-word",
42     "refinement",
43     "op",
44     "native",
45     "number",
46     "integer",
47     "decimal",
48     "pair",
49     "tuple",
50     "char",
51     "logic",
52     "datatype",
53     "time",
54     "date",
55     "action",
56
57     "block",
58     "paren",
59     "path",
60     "lit-path",
61     "set-path",
62     "string",
63     "unicode",
64     "issue",
65     "tag",
66     "file",
67     "binary",
68     "list",
69     "hash",
70     "dec-array",
71     "int-array",
72     "series",
73     "object",
74     "function",
75     "bitset",
76     "error",
77     "port",
78     "struct",
79
80     "image",
81     "sound",
82     "widget",
83     "vec2",
84     "vec3",
85     "matrix",
86     "resource"
87 };
88
89
90 const char* orDatatypeName( int type )
91 {
92     return _datatypes[ type ];
93 }
94
95
96 /*--------------------------------------------------------------------------*/
97
98
99 OEnv* orEnv = 0;
100 char  orTmp[ OR_TMP_SIZE ];
101
102
103 #include "boot.c"
104
105
106 extern OBlock* orTokenize( const char*, const char* );
107 extern const char* orAtomCString( OAtom );
108
109 extern void orBindNative( OValue* );
110 extern void orProtectNative( OValue* );
111 extern void orInNative( OValue* );
112 extern void orUseNative( OValue* );
113 extern void orForeachNative( OValue* );
114
115 extern void orRemoveEachNative();
116
117 extern void orFileNatives();
118 extern void orFormNative( OValue* );
119 extern void orMoldNative( OValue* );
120 extern void orPrintNative( OValue* );
121 extern void orPrinNative( OValue* );
122 extern void orParseNative( OValue* );
123 extern void orDisarmNative( OValue* );
124 extern void orMakeOps();
125 extern void orSeriesNatives();
126 extern void orInstallExceptionHandlers();
127 extern void orMathNatives();
128
129 extern void orFreeBlock( OIndex );
130 extern void orFreeContext( OIndex );
131
132 #ifdef TRACK_MALLOC
133 extern void orMemoryNative( OValue* );
134 #endif
135
136 void orBaseNatives();
137 void orNativeNative( OValue* );
138
139
140 OR_NATIVE( orNop )
141 {
142     //cprint( "KR nop %p %d\n", orEnv->dataStack.buf, orEnv->dataStack.used );
143     orResultUNSET;
144 }
145
146
147 #ifdef DEBUG
148 static void orSizeofNative()
149 {
150     cprint( "sizeof(OValue)     %d\n", (int) sizeof(OValue) );
151     cprint( "sizeof(OArray)     %d\n", (int) sizeof(OArray) );
152     cprint( "sizeof(OWord)      %d\n", (int) sizeof(OWord) );
153     cprint( "sizeof(CallRecord) %d\n", (int) sizeof(CallRecord) );
154 }
155 #endif
156
157
158 static void _appendWord( OBlock* blk, const char* name, int len )
159 {
160     OValue* val;
161     OA_EXPAND1( OValue, blk, val );
162     orSetTF( val, OT_WORD );
163     orSetWord( val, GLOBAL_WORDS_BLKN, GLOBAL_CTXN,
164                OT_UNSET, orInternAtom( name, len ) );
165 }
166
167
168 static void makeGlobalContext()
169 {
170     int i;
171     const char* in;
172     char* out;
173     OBlock* wblk;
174     OBlock* vblk;
175
176
177     // Global context uses first two blocks.
178     vblk = orMakeBlock( 4096 );    // 0 - Values (GLOBAL_CTXN)
179     wblk = orMakeBlock( 4096 );    // 1 - Words  (GLOBAL_WORDS_BLKN)
180
181
182     // Add datatypes first so OT_ define matches the index & atom.
183     // orTypeQNative() depends on this.
184
185     for( i = 0; i < OT_COUNT; ++i )
186     {
187         in  = orDatatypeName( i );
188         out = orTmp;
189         while( *in != '\0' )
190             *out++ = *in++;
191         *out++ = '!';
192
193         _appendWord( wblk, orTmp, out - orTmp );
194         orAppendValue( vblk, OT_DATATYPE, i );
195     }
196
197     _appendWord( wblk, "none", 4 );
198     orAppendNone( vblk );
199
200     {
201         OBlock* dtBlk;
202
203         dtBlk = orMakeBlock( OT_COUNT );
204
205         _appendWord( wblk, "datatypes", 9 );
206         orAppendBlock( vblk, orBlockN(dtBlk) );
207
208         for( i = 0; i < OT_COUNT; ++i )
209             orAppendValue( dtBlk, OT_DATATYPE, i );
210     }
211 }
212
213
214 /**
215   Declares a native function.
216 */
217 void orNative( void* func, const char* name )
218 {
219     OContext ctx;
220     const char* cp;
221     int wrdN;
222
223     cp = name;
224     while( *cp != '\0' )
225         ++cp;
226
227     orGlobalCtx( ctx );
228     wrdN = orLookup( &ctx, orInternAtom( name, cp - name ) );
229     if( wrdN > -1 )
230     {
231         OBlock* blk = orBlockPtr( ctx.vblkN );
232         blk->values[ wrdN ].native.addr = func;
233     }
234     else
235     {
236         dprint( "orNative() - no spec defined for %s\n", name );
237     }
238 }
239
240
241 void orMakeOp( void* func, const char* name )
242 {
243     OContext ctx;
244     OValue* val;
245     const char* cp;
246
247     cp = name;
248     while( *cp != '\0' )
249         ++cp;
250
251     orGlobalCtx( ctx );
252     val = orIntern( &ctx, name, cp - name, 0 );
253
254     orSetTF( val, OT_OP );
255     val->native.addr = func;
256 }
257
258
259 static void orInitAGC( OArrayGC* af )
260 {
261     af->count = 0;
262     af->sweepStart = 0;
263     af->freeList = -2;
264 }
265
266
267 #ifdef BOOT_BYTECODE
268 void evalByteCode( const uint8_t* code )
269 {
270     OIndex len;
271     if( orByteCodeBlock( &code, &len ) )
272     {
273         OBlock* blk = orMakeBlock( len );
274         orRevaluateByteCodes( code, len, blk );
275         orEvalBlock( blk, 0 );
276         orArrayFree( blk );
277     }
278     else
279     {
280         cprint( "** Boot Error: Invalid bytecode\n" );
281     }
282 }
283 #endif
284
285
286 #ifdef DEBUG
287 static void _validateEnv()
288 {
289     int i;
290     OValue val;
291
292 #if 0
293     printf( "sizeof(OValue)      %d\n", sizeof(OValue) );
294     printf( "sizeof(double)      %d\n", sizeof(double) );
295     printf( "sizeof(OWordRef)    %d\n", sizeof(OWordRef) );
296     printf( "sizeof(OSeriesRef)  %d\n", sizeof(OSeriesRef) );
297     printf( "sizeof(ONativeFunc) %d\n", sizeof(ONativeFunc) );
298     printf( "sizeof(OTime)       %d\n", sizeof(OTime) );
299 #endif
300
301     assert( sizeof(OValue) == 16 );
302
303     // Make sure endianess is correct.
304     i = 1;
305 #if defined(__BIG_ENDIAN__)
306     assert(0 == *(char*)&i && "Undefine __BIG_ENDIAN__");
307 #else
308     assert(1 == *(char*)&i && "Define __BIG_ENDIAN__");
309 #endif
310
311     // Make sure double is aligned on 8 byte boundary.
312     assert( ((char*) &val) + 8 == ((char*) &orDecimal(&val)) );
313 }
314 #endif
315
316
317 #if MAKE_ATOM_HEADER
318 #define FIXED_ATOM(str,len,def) \
319     printf( "#define %s\t\t%d\n", #def, orInternAtom(str,len) );
320 #else
321 #ifdef DEBUG
322 #define FIXED_ATOM(str,len,def)     assert( orInternAtom(str,len) == def );
323 #else
324 #define FIXED_ATOM(str,len,def)     orInternAtom(str,len);
325 #endif
326 #endif
327
328
329 // Intern commonly used atoms.
330 static void _createFixedAtoms()
331 {
332 #if MAKE_ATOM_HEADER
333     printf( "// This file is automatically generated - do not edit.\n\n" );
334 #endif
335
336     FIXED_ATOM( "self",         4, OR_ATOM_SELF )
337     FIXED_ATOM( "system",       6, OR_ATOM_SYSTEM )
338     FIXED_ATOM( "script",       6, OR_ATOM_SCRIPT )
339     FIXED_ATOM( "parent",       6, OR_ATOM_PARENT )
340     FIXED_ATOM( "error",        5, OR_ATOM_ERROR )
341     FIXED_ATOM( "error-types", 11, OR_ATOM_ERROR_TYPES )
342     FIXED_ATOM( "catch",        5, OR_ATOM_CATCH )
343     FIXED_ATOM( "throw",        5, OR_ATOM_THROW )
344     FIXED_ATOM( "x",            1, OR_ATOM_X )
345     FIXED_ATOM( "y",            1, OR_ATOM_Y )
346     FIXED_ATOM( "z",            1, OR_ATOM_Z )
347     FIXED_ATOM( "-",            1, OR_ATOM_DASH )
348     FIXED_ATOM( "func",         4, OR_ATOM_FUNC )
349     FIXED_ATOM( "does",         4, OR_ATOM_DOES )
350
351     // Atoms used by parse.
352     FIXED_ATOM( "|",     1, OR_ATOM_BAR )
353     FIXED_ATOM( "opt",   3, OR_ATOM_OPT )
354     FIXED_ATOM( "some",  4, OR_ATOM_SOME )
355     FIXED_ATOM( "any",   3, OR_ATOM_ANY )
356     FIXED_ATOM( "break", 5, OR_ATOM_BREAK )
357     FIXED_ATOM( "skip",  4, OR_ATOM_SKIP )
358     FIXED_ATOM( "set",   3, OR_ATOM_SET )
359     FIXED_ATOM( "copy",  4, OR_ATOM_COPY )
360     FIXED_ATOM( "to",    2, OR_ATOM_TO )
361     FIXED_ATOM( "thru",  4, OR_ATOM_THRU )
362
363
364 #if MAKE_ATOM_HEADER
365     exit(0);
366 #endif
367 }
368
369
370 /**
371   Initialize scripting environment.
372   Call orFreeEnv() when finished with the interpreter.
373
374   If dataStackSize is less than 512 it will be set to 512.
375   If callStackSize is less than 64 it will be set to 64.
376 */
377 void orInitEnv( OEnv* env, int dataStackSize, int callStackSize )
378 {
379     OValue* res;
380
381 #ifdef DEBUG
382     _validateEnv();
383 #endif
384
385     orEnv = env;
386
387     env->error     = 0;
388     env->gcEnabled = 1;
389     env->secure    = 0;
390
391     env->quickHolds     = memAlloc( sizeof(OHold) * OR_MAX_QHOLDS );
392     env->quickHoldsUsed = 0;
393
394     // NOTE: The data & call stacks are never resized so that it is safe
395     // to keep pointers to values on them.
396
397     if( dataStackSize < 512 )
398         dataStackSize = 512;
399     if( callStackSize < 64 )
400         callStackSize = 64;
401
402     orArrayInit( &env->atoms,        sizeof(OIndex),     4096 );
403     orArrayInit( &env->dataStack,    sizeof(OValue),     dataStackSize );
404     orArrayInit( &env->callStack,    sizeof(CallRecord), callStackSize );
405     orArrayInit( &env->holds,        sizeof(OHold),      0 );
406     orArrayInit( &env->loaders,      sizeof(void**),     0 );
407     orArrayInit( &env->devices,      sizeof(void**),     0 );
408
409     orArrayInit( &env->blocks,       sizeof(OBlock),   1024 );
410     orArrayInit( &env->strings,      sizeof(OString),  2048 );
411
412     orInitAGC( &env->freeBlocks );
413     orInitAGC( &env->freeStrings );
414     orInitAGC( &env->freeHolds );
415
416 #ifdef OR_CONFIG_NUMBER_ARRAYS
417     orArrayInit( &env->decArr, sizeof(OArray), 0 );
418     orArrayInit( &env->intArr, sizeof(OArray), 0 );
419
420     orInitAGC( &env->freeDecArr );
421     orInitAGC( &env->freeIntArr );
422 #endif
423
424     orMakeString( 2048 );     // BIN_ATOM_NAMES
425
426     makeGlobalContext();
427
428     _createFixedAtoms();
429
430
431     {
432     // Must manually load native spec.
433     // native: native [spec [block!]]
434     OBlock* blk;
435     OBlock* typeBlk;
436     OValue* wval;
437     OContext ctx;
438
439     blk     = orMakeBlock( 2 );
440     typeBlk = orMakeBlock( 1 );
441
442     orAppendWord( blk, OT_WORD, "spec", 4 );
443     orAppendBlock( blk, orBlockN(typeBlk) );
444
445     orAppendBlock( typeBlk, 0 );
446
447     res = orEnv->dataStack.values;
448     orSetTF( res, OT_BLOCK );
449     orSetSeries( res, orBlockN(blk), 0 );
450     orNativeNative( res );
451
452     orGlobalCtx( ctx );
453     wval = orIntern( &ctx, "native", 6, 0 );
454     *wval = *res;
455
456     orNative( orNativeNative, "native" );
457     }
458
459 #ifdef BOOT_BYTECODE
460     evalByteCode( _natives );
461 #else
462     orEvalCStr( _natives, sizeof(_natives) );
463 #endif
464     if( orErrorThrown )
465     {
466         cprint( "** Boot Error: " );
467         orPrintNative( res );
468     }
469
470     orMakeOps();
471     orBaseNatives();
472     orSeriesNatives();
473     orMathNatives();
474     orFileNatives();
475
476     orInstallExceptionHandlers();
477
478 #ifdef BOOT_BYTECODE
479     evalByteCode( _boot );
480 #else
481     orEvalCStr( _boot, sizeof(_boot) );
482 #endif
483     if( orErrorThrown )
484     {
485         cprint( "** Boot Error: " );
486         orPrintNative( res );
487     }
488
489     {
490     OValue* val;
491
492     // Set system/words to global context.
493     val = orLookupPath( OT_WORD, OR_ATOM_SYSTEM,
494                         OT_WORD, orInternAtom( "words", 5 ),
495                         OR_LPATH_END );
496     if( val )
497     {
498         orSetTF( val, OT_OBJECT );
499         orGlobalCtx( val->ctx );
500     }
501
502     // Set system/os.
503     val = orLookupPath( OT_WORD, OR_ATOM_SYSTEM,
504                         OT_WORD, orInternAtom( "os", 2 ),
505                         OR_LPATH_END );
506     if( val )
507     {
508         OAtom os_atom =
509 #if   defined(__linux)
510         orInternAtom( "linux", 5 );
511 #elif defined(_WIN32)
512         orInternAtom( "windows", 7 );
513 #elif defined(__APPLE__)
514         orInternAtom( "macx", 4 );
515 #elif defined(__SUN__)
516         orInternAtom( "solaris", 7 );
517 #else
518         0;
519 #endif
520         if( os_atom )
521         {
522             orSetTF( val, OT_WORD );
523             val->word.context = GLOBAL_CTXN;
524             val->word.index   = OT_UNSET;
525             val->word.atom    = os_atom;
526         }
527     }
528     }
529
530     // NOTE: Must lock garbage collector after natives are created so that
531     // any spec blocks do not get collected.
532
533     orLockGarbageCollector();
534 }
535
536
537 static void orFreeArrayOfArray( OArray* arr )
538 {
539     if( arr->used )
540     {
541         OArray* it  = (OArray*) arr->buf;
542         OArray* end = it + arr->used;
543         while( it != end )
544         {
545             // Quick version of orArrayFree().
546             if( it->buf )
547                 memFree( it->buf );
548
549             ++it;
550         }
551     }
552
553     orArrayFree( arr );
554 }
555
556
557 void orFreeEnv( OEnv* env )
558 {
559     if( orEnv == env )
560         orEnv = 0;
561
562     orFreeArrayOfArray( &env->blocks );
563     orFreeArrayOfArray( &env->strings );
564
565     orArrayFree( &env->devices );
566     orArrayFree( &env->loaders );
567     orArrayFree( &env->holds );
568     orArrayFree( &env->callStack );
569     orArrayFree( &env->dataStack );
570     orArrayFree( &env->atoms );
571
572 #ifdef OR_CONFIG_NUMBER_ARRAYS
573     orFreeArrayOfArray( &env->decArr );
574     orFreeArrayOfArray( &env->intArr );
575 #endif
576
577     memFree( env->quickHolds );
578
579 #ifdef TRACK_MALLOC
580     extern void memReport( int );
581     memReport( 1 );
582 #endif
583 }
584
585
586 /**
587   Recover from an error.  It does not modify any existing values; nothing
588   is freed and no files are closed.
589   This should only be used from outside a top-level eval call.
590 */
591 void orResetEnv( OEnv* env )
592 {
593     env->callStack.used = 0;
594     env->dataStack.used = 0;
595     env->quickHoldsUsed = 0;
596     env->error = 0;      //orErrorClear;
597 }
598
599
600 OBlock* orMakeList( int len )
601 {
602     OBlock* blk;
603     OValue* it;
604     OValue* end;
605     OValue* next;
606
607     len = len * 2 + 2;
608
609     blk = orMakeBlock( len );
610     blk->used = 2;
611
612     it  = blk->values;
613     end = it + len;
614
615     orSetTF( it, OT_UNSET );
616     it->LIST_PREV = -1;
617     it->LIST_NEXT = 1;
618     it->LIST_FREE = (len == blk->avail) ? 0 : 2;
619     ++it;
620
621     orSetTF( it, OT_UNSET );
622     it->LIST_PREV = 0;
623     it->LIST_NEXT = 0;
624     ++it;
625
626     while( it != end )
627     {
628         next = it + 2;
629
630         orSetTF( it, OT_UNSET );
631         it->LIST_PREV = -1;
632         it->LIST_NEXT = -1;
633         it->LIST_FREE = (next == end) ? 0 : next - blk->values;
634
635         it = next;
636     }
637
638     return blk;
639 }
640
641
642 void orListInsertValue( OBlock* blk, int nodeIndex, OValue* newVal )
643 {
644     int nodeN;
645     OValue* node;
646     OValue* prev;
647     OValue* it = blk->values;
648
649     nodeN = it->LIST_FREE;
650     if( nodeN )
651     {
652         it->LIST_FREE = it[ nodeN ].LIST_FREE;
653     }
654     else
655     {
656         orArrayReserve( blk, sizeof(OValue), blk->used + 2 );
657         nodeN = blk->used;
658         blk->used += 2;
659         it = blk->values;
660     }
661
662     it += nodeIndex;
663
664     prev = blk->values + it->LIST_PREV;
665     prev->LIST_NEXT = nodeN;
666     it->LIST_PREV = nodeN;
667
668     node = blk->values + nodeN;
669     orSetTF( node, OT_UNSET );
670     node->LIST_LINKED = 1;
671     node->LIST_PREV   = prev - blk->values;
672     node->LIST_NEXT   = it - blk->values;
673     node->LIST_FREE   = -1;
674
675     ++node;
676     orCopyV( node, *newVal );
677 }
678
679
680 /*
681    Returns non-zero of successful.
682 */
683 static int orMake( int type, OValue* from, OValue* res )
684 {
685     switch( type )
686     {
687         case OT_WORD:
688         case OT_SETWORD:
689         case OT_GETWORD:
690         case OT_LITWORD:
691             if( orIs(from, OT_STRING) )
692             {
693                 OContext ctx;
694                 OString* str = orSTRING( from );
695                 int start = from->series.it;
696
697                 orGlobalCtx( ctx );
698                 orIntern( &ctx, str->charArray + start,
699                           str->used - start, res );
700                 orSetTF( res, type );
701                 return 1;
702             }
703             else if( orIs(from, OT_WORD) )
704             {
705                 orSetTF( res, type );
706                 res->word = from->word;
707                 return 1;
708             }
709             break;
710
711 #if 0
712         case OT_ACTION:
713             if( from->type == OT_INTEGER )
714             {
715                 orResult( OT_ACTION, orInt(from) );
716                 return 1;
717             }
718             break;
719 #endif
720         case OT_LOGIC:
721             orSetTF( res, OT_LOGIC );
722             orInt(res) =  orInt(from) ? 1 : 0;
723             return 1;
724
725         case OT_INTEGER:
726             if( orIs(from, OT_LOGIC) )
727             {
728                 orSetTF( res, type );
729                 orInt(res) = orInt(from);
730                 return 1;
731             }
732             else if( orIs(from, OT_DECIMAL) )
733             {
734                 orSetTF( res, type );
735                 orInt(res) = (int) orDecimal(from);
736                 return 1;
737             }
738             else if( orIs(from, OT_STRING) )
739             {
740                 OString* str = orSTRING(from);
741                 char* it  = str->charArray + from->series.it;
742                 char* end = str->charArray + str->used;
743                 const char* fin;
744                 int n;
745                 n = orStringToInt( it, end, &fin );
746                 if( fin == end )
747                 {
748                     orSetTF( res, type );
749                     orInt(res) = n;
750                     return 1;
751                 }
752             }
753             break;
754
755         case OT_DECIMAL:
756             if( orIs(from, OT_INTEGER) ||
757                 orIs(from, OT_LOGIC) )
758             {
759                 orSetTF( res, type );
760                 orDecimal(res) = (double) orInt(from);
761                 return 1;
762             }
763             else
764             {
765                 OString* str = orSTRING(from);
766                 char* it  = str->charArray + from->series.it;
767                 char* end = str->charArray + str->used;
768                 const char* fin;
769                 double n;
770                 n = orStringToDec( it, end, &fin );
771                 if( fin == end )
772                 {
773                     orSetTF( res, type );
774                     orDecimal(res) = n;
775                     return 1;
776                 }
777             }
778             break;
779
780         case OT_PAIR:
781             if( orIs(from, OT_BLOCK) )
782             {
783                 OBlock* blk = orBLOCK( from );
784                 OValue* it  = blk->values + from->series.it;
785                 OValue* end = blk->values + blk->used;
786                 if( (end - it) == 2 &&
787                     (it[0].type == OT_INTEGER) &&
788                     (it[1].type == OT_INTEGER) )
789                 {
790                     orSetTF( res, OT_PAIR );
791                     res->pair[0] = it[0].integer;
792                     res->pair[1] = it[1].integer;
793                     return 1;
794                 }
795             }
796             break;
797
798         case OT_TUPLE:
799             if( orIs(from, OT_BLOCK) )
800             {
801                 OBlock* blk = orBLOCK( from );
802                 OValue* it  = blk->values + from->series.it;
803                 OValue* end = blk->values + blk->used;
804                 uint8_t* tuple = res->tuple;
805                 int used = end - it;
806                 if( used <= OR_TUPLE_MAX )
807                 {
808                     while( it != end )
809                     {
810                         if( it->type != OT_INTEGER )
811                             break;
812                         *tuple++ = orInt(it);
813                         ++it;
814                     }
815                     if( it == end )
816                     {
817                         orSetTF( res, OT_TUPLE );
818                         res->argc = tuple - res->tuple;
819                         return 1;
820                     }
821                 }
822             }
823             break;
824
825         case OT_BINARY:
826             if( orIs(from, OT_STRING) )
827             {
828                 OString* str;
829                 OBinary* bin;
830                 int len;
831
832                 str = orSTRING( from );
833                 len = str->used - from->series.it;
834
835                 bin = orMakeBinary( len );
836                 bin->used = len;
837                 memCpy(bin->byteArray, str->charArray + from->series.it, len);
838
839                 orSetTF( res, OT_BINARY );
840                 orSetSeries( res, orBinaryN(bin), 0 );
841                 return 1;
842             }
843             break;
844     }
845
846     return 0;
847 }
848
849
850 extern int orMakeClone( const OContext*, OContext*, OIndex blkN, OIndex blkI );
851 static OBinary* _makeBitset( OBlock* blk, int index );
852
853 OR_NATIVE( orMakeNative )
854 {
855     OValue* a2 = a1 + 1;
856     if( a1->type == OT_DATATYPE )
857     {
858         if( orMake( orInt(a1), a2, a1 ) )
859             return;
860
861         switch( orInt(a1) )
862         {
863             case OT_BLOCK:
864                 if( a2->type == OT_INTEGER )
865                 {
866                     OBlock* blk = orMakeBlock( orInt(a2) );
867                     orResultBLOCK( blk - orBLOCKS );
868                     return;
869                 }
870                 break;
871
872             case OT_STRING:
873                 if( a2->type == OT_INTEGER )
874                 {
875                     OString* str = orMakeString( orInt(a2) );
876                     orResultSTRING( str - orSTRINGS );
877                     return;
878                 }
879                 break;
880
881             case OT_OBJECT:
882                 if( a2->type == OT_BLOCK )
883                 {
884                     OContext ctx;
885                     if( orMakeObject( orBLOCK(a2), a2->series.it, &ctx ) )
886                     {
887                         orSetTF( a1, OT_OBJECT );
888                         a1->ctx = ctx;
889                         return;
890                     }
891                 }
892                 break;
893
894             case OT_BITSET:
895             {
896                 OBinary* bin = 0;
897
898                 switch( a2->type )
899                 {
900                 case OT_STRING:
901                     bin = orMakeCharset( orSTRING(a2), a2->series.it );
902                     break;
903
904                 case OT_BINARY:
905                     bin = orCopyString( a2->index, a2->series.it );
906                     break;
907
908                 case OT_BLOCK:
909                     bin = _makeBitset( orBLOCK(a2), a2->series.it );
910                     break;
911                 }
912
913                 if( bin )
914                 {
915                     orResultSeries( OT_BITSET, orBinaryN(bin), 0 );
916                     return;
917                 }
918             }
919                 break;
920
921             case OT_LIST:
922                 if( a2->type == OT_BLOCK )
923                 {
924                     OBlock* blk = orBLOCK( a2 );
925                     OValue* it  = blk->values + a2->series.it;
926                     OValue* end = blk->values + blk->used;
927                     int len = end - it;
928
929                     blk = orMakeList( len );
930                     while( it != end )
931                     {
932                         orListInsertValue( blk, LIST_TAIL, it );
933                         ++it;
934                     }
935                     orResultSeries( OT_LIST, orBlockN(blk),
936                                     len ? 2 : LIST_TAIL );
937                     return;
938                 }
939                 else if( a2->type == OT_INTEGER )
940                 {
941                     OBlock* blk = orMakeList( orInt(a2) );
942                     orResultSeries( OT_LIST, orBlockN(blk), LIST_TAIL );
943                     return;
944                 }
945                 break;
946 #if 0
947             case OT_FUNCTION:
948                 {
949                 // Return curried function to pick up body argument.
950                 // Too bad we have no way of executing this native.
951                 a1->type  = OT_NATIVE;
952                 a1->flags = 0;
953                 a1->argc  = 1;
954                 a1->refc  = 0;
955                 a1->native.addr    = orFuncNative;
956                 a1->native.specBlk = 0;
957                 }
958                 return;
959 #endif
960
961 #ifdef OR_CONFIG_MATH3D
962             case OT_VEC2:
963             case OT_VEC3:
964                 orSetTF( a1, orInt(a1) );
965                 a1->vec3.x = 0.0f;
966                 a1->vec3.y = 0.0f;
967                 a1->vec3.z = 0.0f;
968                 if( a2->type == OT_BLOCK )
969                     orLoadVectorBlock( &a1->vec3.x, 3, a2 );
970                 return;
971
972             case OT_MATRIX:
973             {
974                 int len = 16 * sizeof(float);
975                 OString* str = orMakeString( len );
976                 str->used = len;
977                 orLoadIdentity( str->floats );
978                 if( a2->type == OT_BLOCK )<