language

some fools attempt at an interpreted language
Log | Files | Refs | README

ns.c (6350B)


      1 #include <stdlib.h>
      2 
      3 #include "ns.h"
      4 #include "var.h"
      5 #include "helper.h"
      6 
      7 /* Initializes namespace context
      8  */
      9 ns_ctx* ns_ctx_init(void)
     10 {
     11 	ns_ctx* new = (ns_ctx*)malloc(sizeof(ns_ctx));
     12 	M_ASSERT(new);
     13 
     14 	new->ptr = 0;
     15 	return new;
     16 }
     17 
     18 void ns_ctx_del(ns_ctx* ctx)
     19 {
     20 	N_ASSERT(ctx, "ns_ctx_del\n");
     21 	free(ctx);
     22 }
     23 
     24 /* Push namespace to context
     25  */
     26 void ns_ctx_push(ns_ctx* ctx, ns_t* ns)
     27 {
     28 	N_ASSERT(ctx, "ns_ctx_push\n");
     29 	N_ASSERT(ns, "ns_ctx_push\n");
     30 
     31 	ASSERT((ctx->ptr + 1) < NS_CTX_DEPTH, "ns_ctx overflow");
     32 
     33 	ctx->spaces[ctx->ptr] = ns;
     34 	ctx->ptr = ctx->ptr + 1;
     35 }
     36 
     37 /* Pop namespace to context
     38  */
     39 ns_t* ns_ctx_pop(ns_ctx* ctx)
     40 {
     41 	N_ASSERT(ctx, "ns_ctx_pop\n");
     42 
     43 	ASSERT((ctx->ptr - 1) >= 0, "ns_ctx underflow");
     44 
     45 	ns_t* rv;
     46 
     47 	ctx->ptr = ctx->ptr - 1;
     48 
     49 	rv = ctx->spaces[ctx->ptr];
     50 
     51 	return rv;
     52 }
     53 
     54 /* Initialize namespace container of size
     55  *  ns_addr - name limit
     56  *  int     - Namespace level
     57  */
     58 ns_cont* ns_cont_init(ns_addr size, int level)
     59 {
     60 	ns_cont* new = (ns_cont*)malloc(sizeof(ns_cont));
     61 	M_ASSERT(new);
     62 
     63 	new->names = (var_cont**)malloc(sizeof(var_cont*)*size);
     64 	M_ASSERT(new->names);
     65 
     66 	new->size = size;
     67 	new->level = level;
     68 
     69 	for (int i = 0; i < size; i++)
     70 	{
     71 		new->names[i] = NULL;
     72 	}
     73 
     74 	new->next = NULL;
     75 
     76 	return new;
     77 }
     78 
     79 /* Initializes namespace of size
     80  *  ns_addr - name limit
     81  */
     82 ns_t* ns_init(ns_addr size)
     83 {
     84 	ns_t* ns = (ns_t*)malloc(sizeof(ns_t));
     85 	M_ASSERT(ns);
     86 
     87 	static unsigned int inc = 0;
     88 
     89 	ns->id = inc;
     90 
     91 	inc++;
     92 
     93 	ns->root = ns_cont_init(size, (ns->id)<<16);
     94 	ns->last = ns->root;
     95 
     96 	return ns;
     97 }
     98 
     99 /* Cleans up memory, returns variable with label to_return
    100  */
    101 var_cont* ns_cont_del(ns_cont* container, ns_addr to_return)
    102 {
    103 	N_ASSERT(container, "ns_cont_del\n");
    104 	N_ASSERT(container->names, "ns_cont_del\n");
    105 
    106 	var_cont* rv = NULL;
    107 
    108 	if (container->names[to_return] != NULL)
    109 	{
    110 		rv = container->names[to_return];
    111 		if (rv->ownership == container->level)
    112 		{
    113 			rv->ownership = -1;
    114 		}
    115 	}
    116 
    117 	for (int i = 0; i < container->size; i++)
    118 	{
    119 		if (i != to_return && container->names[i] != NULL)
    120 		{
    121 			if (container->names[i]->ownership == container->level &&
    122 			   (rv == NULL || container->names[i]->data != rv->data))
    123 			{
    124 				var_del(container->names[i]);
    125 			}
    126 		}
    127 	}
    128 
    129 	free(container->names);
    130 
    131 	free(container);
    132 
    133 	return rv;
    134 }
    135 
    136 void ns_cont_free(ns_cont* container)
    137 {
    138 	N_ASSERT(container, "ns_cont_del\n");
    139 	
    140 	if (container->next != NULL)
    141 	{
    142 		ns_cont_free(container->next);
    143 	}
    144 
    145 	free(container->names);
    146 	free(container);
    147 }
    148 
    149 /* Cleans up memory
    150  */
    151 void ns_del(ns_t* ns)
    152 {
    153 	N_ASSERT(ns, "ns_del\n");
    154 
    155 	if (ns->root != NULL)
    156 	{
    157 		ns_cont_free(ns->root);
    158 	}
    159 
    160 	free(ns);
    161 }
    162 
    163 /* Pushes namespace of size
    164  * ns_t*   - namespace instance
    165  * ns_addr - name limit
    166  */
    167 void ns_push(ns_t* ns, ns_addr size)
    168 {
    169 	N_ASSERT(ns, "ns_push\n");
    170 
    171 	ns_cont* new = ns_cont_init(size, ns->last->level + 1);
    172 
    173 	new->next = ns->last;
    174 	ns->last = new;
    175 }
    176 
    177 /* Pops last namespace level
    178  */
    179 var_cont* ns_pop(ns_t* ns)
    180 {
    181 	N_ASSERT(ns, "ns_pop\n");
    182 
    183 	// Define our return value
    184 	var_cont* rv = NULL;
    185 	// Is this the last link on the chain?
    186 	if (ns->last->next != NULL) {
    187 		// Get the next to last link on the chain
    188 		ns_cont* newlast = ns->last->next;
    189 		// Try to delete that namespace container
    190 		rv = ns_cont_del(ns->last, 0);
    191 		// Set the new last to the last link on the chain
    192 		ns->last = newlast;
    193 	}
    194 
    195 	return rv;
    196 }
    197 
    198 /* Declares a variable, at root or last namespace
    199  *  ns_t*     - Namespace instance
    200  *  b_type    - Type of variable
    201  *  int       - Mux value         [0]
    202  *  ns_addr   - Variable name
    203  *
    204  * @param[0] = namespace level
    205  *  0 -> current namespace
    206  *  1 -> global namespace
    207  */
    208 void ns_dec(ns_t* ns, b_type type, int scope, ns_addr address)
    209 {
    210 	N_ASSERT(ns, "ns_dec\n");
    211 
    212 	// Which namespace are we searching in? (scope == 0 -> local)
    213 	ns_cont* scoped_ns = scope ? ns->root : ns->last;
    214 	// Declare the name in the correct namespace
    215 	ns_cont_dec(scoped_ns, type, address);
    216 }
    217 
    218 /* Declares a variable, at namespace
    219  *  ns_t*     - Namespace instance
    220  *  b_type    - Type of variable
    221  *  ns_addr   - Variable name
    222  */
    223 void ns_cont_dec(ns_cont* container, b_type type, ns_addr address)
    224 {
    225 	N_ASSERT(container, "ns_cont_dec\n");
    226 	// Address must be in range
    227 	SIZE_ASSERT( container->size > address );
    228 	// Initalize a variable container
    229 	var_cont* new_var = var_new(type);
    230 	container->names[ address ] = new_var;
    231 	// Set the ownership of this
    232 	container->names[ address ]->ownership = container->level;
    233 }
    234 
    235 /* Sets variable to value, at root or last namespace
    236  *  ns_t*     - namespace instance
    237  *  int       - mux value         [0]
    238  *  ns_addr   - Variable name
    239  *  var_cont* - Variable
    240  *
    241  * @param[0] = namespace level
    242  * * 0 -> current namespace
    243  * * 1 -> global namespace
    244  */
    245 void ns_set(ns_t* ns, int scope, ns_addr address, var_cont* var)
    246 {
    247 	N_ASSERT(ns, "ns_set\n");
    248 	N_ASSERT(var, "ns_set\n");
    249 
    250 	ns_cont* scoped_ns = scope ? ns->root : ns->last;
    251 
    252 	ns_cont_set(scoped_ns, var, address);
    253 }
    254 
    255 /* Sets variable to value, at root or last namespace
    256  *  ns_cont*  - Namespace instance
    257  *  var_cont* - Variable
    258  *  ns_addr   - Variable name
    259  */
    260 void ns_cont_set(ns_cont* container, var_cont* var, ns_addr address)
    261 {
    262 	N_ASSERT(container, "ns_cont_set\n");
    263 	N_ASSERT(var,       "ns_cont_set\n");
    264 	// Addresss must be in range
    265 	SIZE_ASSERT( container->size > address );
    266 	N_ASSERT(container->names[ address ],
    267 	         "Attempt to set an undeclared variable\n");
    268 
    269 	if (var->ownership < 0)
    270 	{
    271 		// This is my variable now
    272 		var->ownership = container->level;
    273 	}
    274 
    275 	container->names[ address ]->ownership = var->ownership;
    276 
    277 	var_set(container->names[ address ], var->data, var->type);
    278 }
    279 
    280 /* Gets variable from address
    281 
    282  *  ns_t*     - namespace instance
    283  *  int       - mux value         [0]
    284  *  ns_addr   - Variable name
    285  *
    286  * @param[0] = namespace level
    287  *  0 -> current namespace
    288  *  1 -> global namespace
    289  */
    290 var_cont* ns_get(ns_t* ns, int scope, ns_addr address)
    291 {
    292 	N_ASSERT(ns, "ns_get\n");
    293 	N_ASSERT(ns->root, "ns_get\n");
    294 	N_ASSERT(ns->last, "ns_get\n");
    295 
    296 	ns_cont* scoped_ns = scope ? ns->root : ns->last;
    297 
    298 	return ns_cont_get(scoped_ns, address);
    299 }
    300 
    301 /* Gets variable from address
    302  *  ns_t*     - namespace instance
    303  *  ns_addr   - Variable name
    304  */
    305 var_cont* ns_cont_get(ns_cont* container, ns_addr address)
    306 {
    307 	N_ASSERT(container, "ns_cont_get\n");
    308 	SIZE_ASSERT( container->size > address );
    309 
    310 	return container->names[ address ];
    311 }