root/src/rr_context.c

Revision aaca19fb68c3cfe89e2acb105d2c3e8f5e028275, 17.8 kB (checked in by redbrain <redbrain@…>, 2 years ago)

bug fix on many references to single objects in a single context

  • Property mode set to 100644
Line 
1/**
2 * rr_context.c -> Part of Crules Programming language
3 *
4 * Crules is the legal property of its developers. Please refer to the
5 * COPYRIGHT file distributed with this source distribution.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 **/
20
21#ifdef HAVE_CONFIG_H
22# include "config.h"
23#else
24# define CMAKE 1
25# include "config.h.cmake"
26#endif
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31
32#include <unistd.h>
33#include <sys/types.h>
34
35#include <crules/crules.h>
36#include <crules/opcodes.h>
37#include <crules/symbols.h>
38#include <crules/objects.h>
39#include <crules/backend.h>
40#include <crules/runtime.h>
41#include <crules/garbage.h>
42#include <crules/operators.h>
43
44//The runtime table stack!
45crl_context_table *crl_runtime_ctx_table;
46//threshold size alloctor to scale up faster
47#define threshold_alloc(x) (((x)+16)*3/2)
48
49void crl_rr_context_push( crl_branch_context * ctx,
50                          crl_context_table * stack )
51{
52  unsigned int idx= stack->length, tsize= 0;
53  void *pstack= NULL;
54
55  if( !stack || !ctx )
56    crl_fatal("undefined stack or table!\n");
57
58  if( stack->length >= stack->size )
59    {
60      tsize= threshold_alloc( stack->size );
61      pstack= crl_realloc( stack->array,tsize * sizeof(void*) );
62      stack->array= pstack;
63      stack->size= tsize;
64    }
65
66  stack->array[ idx ]= ctx;
67  stack->curr= ctx;
68  idx++; stack->length= idx;
69}
70
71crl_branch_context *
72crl_rr_context_pop( crl_context_table * stack, bool deref )
73{
74  crl_branch_context *ctx = NULL;
75  if( !stack || stack->length <= 0 )
76    return NULL;
77
78  ctx= stack->array[ ((stack->length)-1) ];
79  stack->length--;
80  if( stack->length > 0 )
81    stack->curr= (stack->array[ (stack->length) - 1 ]);
82  else
83    stack->curr= NULL;
84
85  if( deref )
86    {
87      crl_symbol_obj *xret = ctx->return_address;
88      void ** arr = ctx->symbol_stack->array;
89      unsigned int idx = 0;
90      unsigned int n_elms = ctx->symbol_stack->length;
91      for( ; idx<n_elms; ++idx )
92        {
93          crl_symbol_obj *o = (crl_symbol_obj*) arr[ idx ];
94          if( o )
95            {
96              if( o != xret )
97                {
98                  o->n_ref--;
99                  crl_debug("de-referencing object <%p> to count <%i>!\n",
100                            (void*)o, o->n_ref );
101                }
102            }
103        }
104
105      // def any local symbols pointing to the objects!
106      idx = 0; crl_table_entry *c_arr = ctx->symbol_table->array;
107      for( ; idx<(ctx->symbol_table->size); ++idx )
108        {
109          crl_symbol_obj *o = c_arr[idx].symbol;
110
111          if( o )
112            {
113              o->n_ref--;
114              crl_debug("de-referencing object <%p> to count <%i>!\n",
115                        (void*)o, o->n_ref );
116            }
117        }     
118    }
119
120  return ctx;
121}
122
123void crl_rr_context_init_table( crl_context_table ** table )
124{
125  if( table )
126    {
127      unsigned int xlen= threshold_alloc( 0 );
128      (*table)->array= crl_calloc( xlen, sizeof( crl_branch_context * ) );
129      (*table)->size= xlen; (*table)->length= 0;
130      (*table)->curr= NULL;
131    }
132  else
133    {
134      crl_error("null table refernce to a table in table init!\n");
135    }
136}
137
138unsigned int
139crl_rr_context_get_table_size( crl_context_table * stack )
140{
141  unsigned int retval;
142  if( !stack )
143    retval= 0;
144  else
145    retval= (stack->length);
146
147  return retval;
148}
149
150crl_table_entry *
151crl_rr_context_lookup_symbol( const char* identifier,
152                              crl_context_table ** stack )
153{
154  crl_table_entry *retval;
155  if( stack )
156    {
157      crl_hash_t h= crl_dd_hash_hash( identifier );
158      crl_debug("looking up symbol '%s' - hash 0x%X\n",
159                identifier, h);
160
161      signed int idx= crl_rr_context_get_table_size( (*stack) );
162      crl_debug("stack frame size :: '%i'!\n", idx );
163      crl_branch_context* ctx= NULL; idx--;
164
165      retval= NULL;
166      while( idx >= 0 )
167        {
168          ctx= ( (*stack)->array[ idx ] );
169          crl_table_entry *ent= NULL;
170
171          if( ctx->symbol_table->array )
172            ent= crl_dd_hash_lookup_table( ctx->symbol_table, h );
173
174          if( ent )
175            {
176              if( ent->symbol )
177                {
178                  crl_debug("found symbol <%s> hash <0x%X> frame <%i> addr <%p> ref count <%u>!\n", 
179                            identifier, h, (idx+1), (void *) ent->symbol, ent->symbol->n_ref );
180                  retval= ent;
181                  break;
182                }
183            }
184          idx--;
185        }
186    }
187  else
188    {
189      crl_error("null stack table for lookup!\n");
190      retval= NULL;
191    }
192  return retval;
193}
194
195crl_symbol_obj**
196crl_rr_context_lookup_function_def( const char* identifier,
197                                    crl_context_table ** stack )
198{
199  crl_symbol_obj **retval = NULL;
200  if( stack )
201    {
202      crl_hash_t h= crl_dd_hash_hash( identifier );
203      crl_debug( "looking up function '%s' - hash 0x%X\n",
204                 identifier, h );
205
206      signed int idx= crl_rr_context_get_table_size( (*stack) );
207      crl_debug("stack frame size :: '%i'!\n", idx );
208      crl_branch_context* ctx= NULL; idx--;
209
210      retval= NULL;
211      while( idx >= 0 )
212        {
213          ctx= ( (*stack)->array[ idx ] );
214          crl_table_entry *ent= NULL;
215
216          if( ctx->function_table->array )
217            ent= crl_dd_hash_lookup_table( ctx->function_table, h );
218
219          if( ent )
220            {
221              if( ent->symbol )
222                {
223                  crl_debug("found symbol function <%s> - hash <0x%X> frame <%i> addr <%p>!\n", 
224                            identifier, h, (idx+1), (void *) ent->symbol );
225                  retval= &(ent->symbol);
226                  break;
227                }
228            }
229          idx--;
230        }
231    }
232  else
233    {
234      crl_error("null stack table for lookup!\n");
235      retval = NULL;
236    }
237  return retval;
238}
239
240crl_type_obj_def_t **
241crl_rr_context_lookup_object_def( const char * identifier,
242                                  crl_context_table ** stack )
243{
244  crl_type_obj_def_t ** retval = NULL;
245  if( stack )
246    {
247      crl_hash_t h= crl_dd_hash_hash( identifier );
248      crl_debug( "looking up defintion '%s' - hash 0x%X\n",
249                 identifier, h );
250
251      signed int idx= crl_rr_context_get_table_size( (*stack) );
252      crl_debug("stack frame size :: '%i'!\n", idx );
253      crl_branch_context* ctx= NULL; idx--;
254
255      retval= NULL;
256      while( idx >= 0 )
257        {
258          ctx= ( (*stack)->array[ idx ] );
259          crl_table_entry *ent= NULL;
260
261          if( ctx->object_table->array )
262            ent= crl_dd_hash_lookup_table( ctx->object_table, h );
263
264          if( ent )
265            {
266              if( ent->symbol )
267                {
268                  crl_debug("found object definition <%s> - hash <0x%X> frame <%i> addr <%p>!\n", 
269                            identifier, h, (idx+1), (void*) ent->symbol );
270                  crl_assert( ent->symbol->type == STRUCTURE_OBJECT_DEF );
271                  retval= &( ent->symbol->op_a.object_def );
272                  crl_debug("got object def address!\n");
273                  break;
274                }
275            }
276          idx--;
277        }
278    }
279  else
280    {
281      crl_error("null stack table for lookup!\n");
282      retval = NULL;
283    }
284  return retval;
285}
286
287bool crl_rr_context_push_function_def( crl_symbol_obj * functor,
288                                       crl_context_table ** context )
289{
290  bool retval = true;
291  crl_symbol_obj** f = crl_rr_context_lookup_function_def( functor->identifier, context );
292  if( !f )
293    {
294      // not defined!
295      crl_symbol_obj **s= crl_dd_hash_insert( crl_dd_hash_hash( functor->identifier ),
296                                              functor, ((*context)->curr->function_table) );
297      // this shouldn't happen!
298      if( s )
299        {
300          crl_error("problem assigning '%s'!\n", functor->identifier );
301          retval = false;
302        }
303    }
304  else
305    {
306      // already defined!
307      retval = false;
308      crl_error( "error pushing function definition <%s> is already defined!\n",
309                 functor->identifier );
310    }
311  return retval;
312}
313
314static
315void crl_rr_obj_init_members( struct crl_builtin_member_def_t * members,
316                              crl_branch_context * obj_ctx )
317{
318  return;
319}
320
321struct crl_number_prot_t *
322crl_rr_context_clone_n_prot( struct crl_number_prot_t * prot )
323{
324  struct crl_number_prot_t * retval = NULL;
325  if( prot )
326    {
327      retval = crl_malloc( sizeof(struct crl_number_prot_t) );
328      retval->init = prot->init;
329      retval->n_add = prot->n_add;
330      retval->n_sub = prot->n_sub;
331      retval->n_div = prot->n_div;
332      retval->n_mul = prot->n_mul;
333      retval->n_pow = prot->n_pow;
334      retval->n_let = prot->n_let;
335      retval->n_lee = prot->n_lee;
336      retval->n_get = prot->n_get;
337      retval->n_gee = prot->n_gee;
338      retval->n_eee = prot->n_eee;
339      retval->n_nee = prot->n_nee;
340      retval->n_orr = prot->n_orr;
341      retval->n_and = prot->n_and;
342    }
343  return retval;
344}
345
346bool crl_rr_context_init_member_functions( crl_branch_context * context ,
347                                           struct crl_builtin_function_def_t * functions )
348{
349  bool retval = true;
350  unsigned int idx = 0;
351  while( functions[idx].identifier != NULL )
352    {
353      crl_debug("initilizing member <%s>!\n", functions[idx].identifier );
354      crl_symbol_obj *o;
355      Crl_Symbol_Init( o );
356
357      struct crl_builtin_function_def_t * call =
358        crl_malloc( sizeof(struct crl_builtin_function_def_t) );
359      call->identifier = crl_strdup( functions[idx].identifier );
360      memcpy( &(call->n_parameters), &(functions[idx].n_parameters),
361              sizeof(int) );
362      call->callback = functions[idx].callback;
363
364      o->identifier = crl_strdup( functions[idx].identifier );
365      o->type = TYPE_BUILTIN_CALLBACK;
366      o->op_a_t = TYPE_BUILTIN_CALLBACK;
367      o->op_a.callback = call;
368
369      crl_symbol_obj **s= crl_dd_hash_insert( crl_dd_hash_hash( functions[idx].identifier ),
370                                              o, (context->function_table) );
371      // this shouldn't happen!
372      if( s )
373        {
374          crl_error("error inserting table defined function <%s> idx <%i>!\n",
375                    functions[idx].identifier, idx );
376          retval = false;
377          break;
378        }
379      idx++;
380    }
381  return retval;
382}
383
384bool crl_rr_context_push_obj_def( crl_symbol_obj * obj_def,
385                                  crl_context_table ** context )
386{
387  bool retval = true;
388  crl_assert( obj_def->op_a_t == TYPE_STRING );
389  crl_debug("trying to push module definition <%s>!\n", obj_def->op_a.string );
390 
391  crl_type_obj_def_t ** chk = crl_rr_context_lookup_object_def( obj_def->op_a.string,
392                                                                context );
393  if( chk )
394    {
395      crl_error("object <%s> is already defined!\n", obj_def->op_a.string );
396      retval = false;
397    }
398  else
399    {
400      crl_branch_context *ctx= (crl_branch_context*)
401        crl_malloc(sizeof( crl_branch_context ));
402      crl_rr_context_init( &ctx );
403      crl_context_table * o_ctx = (crl_context_table *)
404        crl_malloc( sizeof(crl_context_table) );
405      crl_rr_context_init_table( &(o_ctx) );
406
407      crl_rr_context_push( ((*context)->array[0]), o_ctx );
408      crl_rr_context_push( ctx, o_ctx );
409
410      crl_assert( obj_def->op_b_t == TYPE_SYMBOL );
411      crl_symbol_obj * t1 = crl_runtime_exec_branch( obj_def->op_b.symbol_table,
412                                                     o_ctx );
413      if( t1 ) { crl_garbage_mark_obj( &t1 ); }
414      crl_branch_context *c_ctx = crl_rr_context_pop( o_ctx,false );
415      if( c_ctx != ctx )
416        {
417          crl_fatal("corruption in context table!\n");
418        }
419      crl_rr_context_pop( o_ctx, false );
420      crl_garbage_free_context_table( &(o_ctx) );
421
422      struct crl_type_obj_def_t * obj = (struct crl_type_obj_def_t *)
423        crl_malloc(sizeof(struct crl_type_obj_def_t));
424 
425      obj->identifier = crl_strdup( obj_def->op_a.string );
426      obj->builtin_type_size = 0;
427      obj->init_hook = NULL;
428      obj->destroy_hook = NULL;
429      obj->print_hook = NULL;
430      obj->context = ctx;
431      obj->binary_protocol = NULL;
432      obj->member_fields = NULL;
433      obj->member_functions = NULL;
434      obj->builtin = false;
435
436      crl_symbol_obj * oo;
437      Crl_Symbol_Init( oo );
438      oo->type = STRUCTURE_OBJECT_DEF;
439      oo->op_a_t = STRUCTURE_OBJECT_DEF;
440      oo->op_a.object_def = obj;
441
442      crl_debug("trying to insert object def <%s> <%p>!\n", obj_def->op_a.string, (void *)oo );
443      crl_symbol_obj **s= crl_dd_hash_insert( crl_dd_hash_hash( obj_def->op_a.string ),
444                                              oo, ((*context)->curr->object_table) );
445      if( s )
446        {
447          crl_error("error inserting object definition <%s>!\n", obj_def->op_a.string );
448          retval = false;
449        }
450    }
451  return retval;
452}
453
454bool crl_rr_context_push_type_def( struct crl_type_obj_def_t * type_def,
455                                   crl_context_table ** context )
456{
457  bool retval = true;
458  crl_debug("trying to push module definition <%s>!\n", type_def->identifier );
459  crl_type_obj_def_t ** chk = crl_rr_context_lookup_object_def( type_def->identifier,
460                                                                context );
461  if( chk )
462    {
463      crl_error("object <%s> is already defined!\n", type_def->identifier );
464      retval = false;
465    }
466  else
467    {
468      crl_symbol_obj * obj;
469      Crl_Symbol_Init( obj );
470
471      struct crl_type_obj_def_t * obj_def = (struct crl_type_obj_def_t *)
472        crl_malloc(sizeof(struct crl_type_obj_def_t));
473      obj_def->identifier = crl_strdup( type_def->identifier );
474      memcpy( &(obj_def->builtin_type_size), &(type_def->builtin_type_size),
475              sizeof( size_t ) );
476      obj_def->init_hook = type_def->init_hook;
477      obj_def->destroy_hook = type_def->destroy_hook;
478      obj_def->print_hook = type_def->print_hook;
479
480      crl_branch_context *ctx= type_def->context;
481      if( !ctx )
482        {
483          ctx= crl_malloc( sizeof( crl_branch_context ) );
484          crl_rr_context_init( &ctx );
485        }
486      if( type_def->member_fields ) {
487        crl_rr_obj_init_members( type_def->member_fields, ctx );
488      }
489
490      crl_rr_context_init_member_functions( ctx, type_def->member_functions );
491
492      obj_def->context = ctx;
493      obj_def->binary_protocol = crl_rr_context_clone_n_prot( type_def->binary_protocol );
494      obj_def->member_fields = NULL;
495      obj_def->member_functions = NULL;
496      obj_def->builtin = true;
497
498      obj->type = STRUCTURE_OBJECT_DEF;
499      obj->op_a_t = STRUCTURE_OBJECT_DEF;
500      obj->op_a.object_def = obj_def;
501
502      crl_debug("trying to insert object def <%s> <%p>!\n", type_def->identifier, (void *) obj );
503      crl_symbol_obj **s= crl_dd_hash_insert( crl_dd_hash_hash( type_def->identifier ),
504                                              obj, ((*context)->curr->object_table) );
505      if( s )
506        {
507          crl_error("error inserting object definition <%s>!\n", type_def->identifier );
508          retval = false;
509        }
510    }
511  return retval;
512}
513
514void crl_rr_context_init( crl_branch_context ** branch )
515{
516  if( branch )
517    {
518      (*branch)->return_address= NULL;
519      (*branch)->return_ctx= false;
520      (*branch)->loop_ctx= false;
521
522      (*branch)->symbol_table= (crl_table_t *)
523        crl_malloc( sizeof( crl_table_t ) );
524      (*branch)->function_table= (crl_table_t *)
525        crl_malloc( sizeof( crl_table_t ) );
526      (*branch)->object_table= (crl_table_t *)
527        crl_malloc( sizeof( crl_table_t ) );
528
529      (*branch)->symbol_stack = (crl_stack_t *)
530        crl_malloc( sizeof(crl_stack_t) );
531      crl_dd_stack_init( &((*branch)->symbol_stack) );
532
533      crl_dd_hash_init_table( &((*branch)->symbol_table) );
534      crl_dd_hash_init_table( &((*branch)->function_table) );
535      crl_dd_hash_init_table( &((*branch)->object_table) );
536    }
537  else
538    {
539      crl_error("null branch context to init!\n");
540    }
541}
542
543/**
544 * WARNING:
545 *   This will not clone the return address even if it exists!
546 *
547 * workaround: if your using this function you then have the reference to the
548 * context you want to clone do:
549 *
550 * crl_branch_context *ctx = crl_context_clone_branch( &cloneme );
551 * if( (ctx->return_ctx) || (ctx->loop_ctx) ) {
552 *   ctx->return_address = crl_runtime_obj_clone( cloneme->return_address, ... );
553 * }
554 *
555 * @param ctx the context to clone
556 * @returns returns address to cloned context
557 **/
558crl_branch_context *
559crl_rr_context_clone_branch( crl_branch_context ** ctx )
560{
561  crl_branch_context * retval = (crl_branch_context*)
562    crl_malloc(sizeof(crl_branch_context));
563
564  if( ctx )
565    {
566      retval->return_ctx = (*ctx)->return_ctx;
567      retval->loop_ctx = (*ctx)->loop_ctx;
568
569      retval->symbol_table = crl_dd_hash_clone_table( &((*ctx)->symbol_table) );
570      retval->function_table = crl_dd_hash_clone_table( &((*ctx)->function_table) );
571      retval->object_table = crl_dd_hash_clone_table( &((*ctx)->object_table) );
572    }
573  return retval;
574}
575
576crl_obj_state_t *
577crl_rr_context_clone_obj_state( crl_obj_state_t ** obj_s )
578{
579  crl_debug("clone object state!\n");
580  crl_obj_state_t *retval = NULL;
581  if( obj_s )
582    {
583      retval = (crl_obj_state_t *)
584        crl_malloc( sizeof(crl_obj_state_t) );
585
586      struct crl_type_obj_def_t ** def = (*obj_s)->definition;
587      void * s = crl_malloc( (*def)->builtin_type_size );
588      memcpy( s, (*obj_s)->self, (*def)->builtin_type_size );
589      retval->self = s;
590
591      retval->identifier = crl_strdup( (*obj_s)->identifier );
592      retval->context = crl_rr_context_clone_branch( &((*obj_s)->context) );
593      retval->definition = (*obj_s)->definition;
594    }
595  return retval;
596}
597
598bool crl_rr_context_intilize_module( struct crl_type_obj_def_t * module_def,
599                                     crl_context_table * context )
600{
601  bool retval = false;
602
603  retval = crl_rr_context_push_type_def( module_def, &context );
604
605  return retval;
606}
607
608/**
609 * Initilizes the memory tables and different
610 * symbol tables
611 **/
612bool crl_init_tables( void )
613{
614  crl_debug("Initilizing...\n");
615
616  crl_branch_context *ctx= (crl_branch_context*)
617    crl_malloc(sizeof( crl_branch_context ));
618  crl_rr_context_init( &ctx );
619
620  crl_runtime_ctx_table= (crl_context_table*)
621    crl_malloc(sizeof( crl_context_table ));
622  crl_rr_context_init_table( &crl_runtime_ctx_table );
623  crl_rr_context_push( ctx, crl_runtime_ctx_table );
624
625  /* Init object types and modules! */
626  crl_builtin_modules_init( crl_runtime_ctx_table );
627
628  crl_debug("System tables initilized!\n");
629
630  pid_t pid;
631  /* get the process id */
632  if( (pid = getpid( ) ) < 0 )
633    {
634      crl_warning( "unable to get program pid" );
635    }
636  else
637    {
638      crl_debug( "started with pid <%d>!\n", pid );
639    }
640  return true;
641}
Note: See TracBrowser for help on using the browser.