MCPcopy Create free account
hub / github.com/ElementsProject/elements / runTCO

Function runTCO

src/simplicity/eval.c:286–520  ·  view source on GitHub ↗

Starting from the Bit Machine 'state', * run the machine with the TCO (off) program generated by the well-typed Simplicity expression 'dag[len]' of type 'A |- B'. * If some jet execution fails, returns 'SIMPLICITY_ERR_EXEC_JET'. * If some 'assertr' or 'assertl' combinator fails, returns 'SIMPLICITY_ERR_EXEC_ASSERT'. * Otherwise returns 'SIMPLICITY_NO_ERROR'. * * The 'state' of the Bit Machin

Source from the content-addressed store, hash-verified

284 * if 'dag[len]' represents a Simplicity expression with primitives then 'NULL != env';
285 */
286static simplicity_err runTCO(evalState state, call* stack, const dag_node* dag, type* type_dag, size_t len, const txEnv* env) {
287/* The program counter, 'pc', is the current combinator being interpreted. */
288 size_t pc = len - 1;
289
290/* 'stack' represents the interpreter's call stack.
291 * However, the stack is not directly represented as an array.
292 * Instead, the bottom of the call stack is located at 'stack[len - 1]' and the top of the call stack is located at 'stack[pc]'.
293 * The intermediate call stack items are somewhere between 'pc' and 'len - 1'.
294 * The each call stack item references the one below it through the 'stack[i].return_to' values.
295 * The bottom of the stack's '.return_to' value is set to 'len' which is an out-of-bounds index.
296 *
297 * During CALLs, a new 'stack[i]' value is created where 'i' is index of the combinator being called,
298 * and 'stack[i].return_to' is set to the current 'pc' value.
299 * During TAIL_CALLs, 'stack[i].return_to' is instead set to the 'stack[pc].return_to' value.
300 * During RETURNs, the 'pc' is set to the 'stack[pc].return_to' value.
301 * TAIL_CALLs allows for faster returns within the interpreter (unrelated to Simplicity's TCO),
302 * skipping over intermediate combinators.
303 */
304 stack[pc].return_to = len;
305 set_tco_flag(&stack[pc], false);
306
307/* 'calling' lets us know if we are entering a CALL or returning from a CALL. */
308 bool calling = true;
309
310 /* :TODO: Use static analysis to limit the number of iterations through this loop. */
311 while(pc < len) {
312 stack[pc].flags |= FLAG_EXEC;
313 tag_t tag = dag[pc].tag;
314 simplicity_debug_assert(state.activeReadFrame < state.activeWriteFrame);
315 simplicity_debug_assert(state.activeReadFrame->edge <= state.activeWriteFrame->edge);
316 if (dag[pc].jet) {
317 if(!dag[pc].jet(state.activeWriteFrame, *state.activeReadFrame, env)) return SIMPLICITY_ERR_EXEC_JET;
318 /* Like IDEN and WITNESS, we want to "fallthrough" to the UNIT case. */
319 tag = UNIT;
320 }
321 switch (tag) {
322 case COMP:
323 if (calling) {
324 /* NEW_FRAME(BITSIZE(B)) */
325 *(state.activeWriteFrame - 1) = initWriteFrame(type_dag[COMP_B(dag, type_dag, pc)].bitSize, state.activeWriteFrame->edge);
326 state.activeWriteFrame--;
327
328 /* CALL(dag[pc].child[0], SAME_TCO) */
329 stack[dag[pc].child[0]].return_to = pc;
330 set_tco_flag(&stack[dag[pc].child[0]], get_tco_flag(&stack[pc]));
331 pc = dag[pc].child[0];
332 } else {
333 /* MOVE_FRAME */
334 simplicity_debug_assert(0 == state.activeWriteFrame->offset);
335 memmove( state.activeReadFrame->edge, state.activeWriteFrame->edge
336 , (size_t)((state.activeWriteFrame + 1)->edge - state.activeWriteFrame->edge) * sizeof(UWORD)
337 );
338 *(state.activeReadFrame + 1) = initReadFrame(type_dag[COMP_B(dag, type_dag, pc)].bitSize, state.activeReadFrame->edge);
339 state.activeWriteFrame++; state.activeReadFrame++;
340
341 /* TAIL_CALL(dag[pc].child[1], true) */
342 calling = true;
343 stack[dag[pc].child[1]].return_to = stack[pc].return_to;

Callers 1

Calls 15

set_tco_flagFunction · 0.85
initWriteFrameFunction · 0.85
COMP_BFunction · 0.85
get_tco_flagFunction · 0.85
initReadFrameFunction · 0.85
peekBitFunction · 0.85
forwardFunction · 0.85
padFunction · 0.85
CASE_AFunction · 0.85
CASE_BFunction · 0.85
set_case_last_flagFunction · 0.85
backwardFunction · 0.85

Tested by

no test coverage detected