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