language

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

proc.c (4945B)


      1 #include <stdlib.h>
      2 #include <stdio.h>
      3 
      4 #include "proc.h"
      5 
      6 #include "rt.h"
      7 #include "ins_def.h"
      8 #include "bc.h"
      9 #include "stk.h"
     10 #include "var.h"
     11 #include "ns.h"
     12 #include "pc.h"
     13 #include "helper.h"
     14 
     15 /* Initializes process, returns runtime context.
     16  *  char* - Filename of valid bytecode
     17  */
     18 rt_t* proc_init(char* fname)
     19 {
     20 	N_ASSERT(fname, "proc_init\n");
     21 	rt_t* ctx = rt_ctx_new(fname, stk_new());
     22 
     23 	return ctx;
     24 }
     25 
     26 void printstk(char* name, stk_t* stk)
     27 {
     28 	printf("\t\t%s: %i: ", name, stk->stack->ptr);
     29 	for (int i = 0; i < stk->stack->ptr; i++)
     30 	{
     31 		var_cont* test = stk_at(stk, i);
     32 
     33 		printf("%i, ", test->type);
     34 	}
     35 	printf("\n");
     36 }
     37 
     38 void proc_printstate(rt_t* ctx)
     39 {
     40 	printf("-[ns-%li] [%li]:\t", ctx->vars->id, ctx->pc->address);
     41 	bc_print_op(ctx->pc->line);
     42 	printf("\n");
     43 
     44 	printstk("   STK", ctx->stack);
     45 	printstk("ARGSTK", ctx->argstk);
     46 	printf("------------------------------------------------------------------------------\n");
     47 }
     48 
     49 /* Starts execution loop for a runtime context
     50  * rt_t* - Runtime context
     51  */
     52 inline void proc_run(rt_t* ctx)
     53 {
     54 	N_ASSERT(ctx, "proc_run\n");
     55 
     56 	int n;
     57 	
     58 	for (n = 0; pc_safe(ctx->pc); pc_update(ctx->pc))
     59 	{
     60 		if (ctx->db)
     61 		{
     62 			proc_printstate(ctx);
     63 		}
     64 
     65 		run_ins(ctx, ctx->pc->line);
     66 
     67 		n++;
     68 	}
     69 }
     70 
     71 /* Runs exection loop until a return is reached
     72  */
     73 inline void proc_run_to_return(rt_t* ctx)
     74 {
     75 	N_ASSERT(ctx, "proc_run_to_return\n");
     76 
     77 	int n;
     78 	for (n = 0; pc_safe(ctx->pc); pc_update(ctx->pc))
     79 	{
     80 		if (ctx->db)
     81 		{
     82 			proc_printstate(ctx);
     83 		}
     84 
     85 		if (ctx->pc->line->op == 0x7F || ctx->pc->line->op == 0x82)
     86 		{
     87 			n++;
     88 		}
     89 
     90 		run_ins(ctx, ctx->pc->line);
     91 
     92 		// Break when the function returns
     93 		
     94 		if (ctx->pc->line->op == 0xF0)
     95 		{
     96 			if (n > 0)
     97 			{
     98 				n--;
     99 			} else
    100 			{
    101 				break;
    102 			}
    103 		}
    104 	}
    105 }
    106 
    107 /* Calls runtime context elements to free memory and terminate
    108  *  rt_t* - Runtime context
    109  */
    110 void proc_clean(rt_t* ctx)
    111 {
    112 	N_ASSERT(ctx, "proc_clean\n");
    113 	rt_ctx_del(ctx);
    114 }
    115 
    116 /* Set a variable subroutine
    117  *  rt_t*     - Runtime context
    118  *  b_type    - Type
    119  *  int       - Scope
    120  *  ns_addr   - Name of variable
    121  *
    122  *  This function is used to support an interface to multithreaded instances
    123  */
    124 void proc_decvar(rt_t* ctx, b_type type, int scope, ns_addr name)
    125 {
    126 	N_ASSERT(ctx, "proc_decvar\n");
    127 
    128 	int x = (scope & 0xFE) >> 1;
    129 	int s = (scope & 0x01);
    130 
    131 	if (x == 0)
    132 	{
    133 		ns_dec(ctx->vars, type, s, name);
    134 	}
    135 }
    136 
    137 /* Set a variable subroutine
    138  *  rt_t*     - Runtime context
    139  *  int       - Scope
    140  *  ns_addr   - Name of variable
    141  *  var_cont* - Variable container
    142  *
    143  *  This function is used to support an interface to multithreaded instances
    144  */
    145 void proc_setvar(rt_t* ctx, int scope, ns_addr name, var_cont* var)
    146 {
    147 	N_ASSERT(ctx, "proc_setvar\n");
    148 
    149 	int x = (scope & 0xFE) >> 1;
    150 	int s = (scope & 0x01);
    151 
    152 	if (x == 0)
    153 	{
    154 		ns_set(ctx->vars, s, name, var);
    155 	} else
    156 	{
    157 		var_cont* ns_var = ns_get(ctx->names, 1, x);
    158 		ns_t* object = object_get(ns_var);
    159 
    160 		ns_set(object, s, name, var);
    161 	}
    162 }
    163 
    164 /* Get a variable subroutine
    165  *  rt_t*   - Runtime context
    166  *  int     - Scope
    167  *  ns_addr - Name of variable
    168  */
    169 var_cont* proc_getvar(rt_t* ctx, int scope, ns_addr name)
    170 {
    171 	N_ASSERT(ctx, "proc_getvar\n");
    172 	var_cont* rv;
    173 
    174 	int x = (scope & 0xFE) >> 1;
    175 	int s = (scope & 0x01);
    176 
    177 	if (x == 0)
    178 	{
    179 		rv = ns_get(ctx->vars, scope, name);
    180 	} else
    181 	{
    182 		var_cont* ns_var = ns_get(ctx->names, 1, x);
    183 		ns_t* object = object_get(ns_var);
    184 
    185 		rv = ns_get(object, s, name);
    186 	}
    187 
    188 	return rv;
    189 }
    190 
    191 /* Call a function
    192  */
    193 void proc_function_call(rt_t* ctx, int scope, ns_addr name)
    194 {
    195 	N_ASSERT(ctx, "proc_function_call\n");
    196 
    197 	int x = (scope & 0xFE) >> 1;
    198 
    199 	var_cont* var = proc_getvar(ctx, scope, name);
    200 
    201 	if (x != 0)
    202 	{
    203 		ns_ctx_push(ctx->varctx, ctx->vars);
    204 
    205 		var_cont* ns_var = ns_get(ctx->names, 1, x);
    206 		ns_t* object = object_get(ns_var);
    207 
    208 		ctx->vars = object;
    209 	}
    210 
    211 	var_data_func* func = var_data_get_FUNC(var);
    212 	
    213 	proc_function_call_handle(ctx, func);
    214 
    215 	pc_update(ctx->pc);
    216 
    217 	proc_run_to_return(ctx);
    218 
    219 	if (x != 0)
    220 	{
    221 		ctx->vars = ns_ctx_pop(ctx->varctx);
    222 	}
    223 }
    224 
    225 /* Handles arguements and namespace procedures for a given
    226  * function call
    227  */
    228 void proc_function_call_handle(rt_t* ctx, var_data_func* func)
    229 {
    230 	// Push a new namespace of specified size
    231 	ns_push(ctx->vars, func->size);
    232 	// Declare the return value
    233 	ns_dec(ctx->vars, func->type, 0, 0);
    234 
    235 	// Throw in the arguements on the arguement stack into the new namespace
    236 	int offset = 1;
    237 	int i;
    238 	for (i = 0; i < func->paramlen; i++)
    239 	{
    240 		// Pop the arguement stack
    241 		var_cont* arg = stk_pop(ctx->argstk);
    242 
    243 		// Is the arguement of the right type?
    244 		ASSERT(arg->type == func->param[i], "Invalid arguement stack\n");
    245 
    246 		// Declare the name in the new namespace and pass the arguements
    247 		ns_dec(ctx->vars, arg->type, 0, i+offset);
    248 		ns_set(ctx->vars, 0, i+offset, arg);
    249 	}
    250 
    251 	// Push new stack levels for the stack and the arguement stack
    252 	stk_newlevel(&ctx->stack);
    253 	stk_newlevel(&ctx->argstk);
    254 
    255 	// Branch to functions body
    256 	pc_branch(ctx->pc, func->loc);
    257 }
    258