// FOR who IN what WHERE where DO how static bool iterate(struct context *context, enum Opcode op, struct program_state *state, struct byte_array *program) { struct byte_array *who = serial_decode_string(program); struct byte_array *where = serial_decode_string(program); struct byte_array *how = serial_decode_string(program); #ifdef DEBUG DEBUGPRINT("%s %s\n", NUM_TO_STRING(opcodes, op), byte_array_to_string(who)); if (!context->runtime) { if (where && where->length) { DEBUGPRINT("%s\tWHERE\n", indentation(context)); display_code(context, where); } DEBUGPRINT("%s\tDO\n", indentation(context)); display_code(context, how); return false; } #endif bool comprehending = (op == VM_COM); struct variable *result = comprehending ? variable_new_list(context, NULL) : NULL; struct variable *what = variable_pop(context); uint32_t len = variable_length(context, what); for (int i=0; i<len; i++) { struct variable *that = list_get_int(context, what, i); set_named_variable(context, state, who, that); byte_array_reset(where); byte_array_reset(how); if (where && where->length) run(context, where, NULL, true); if (!where || !where->length || test_operand(context)) { if (run(context, how, NULL, true)) // true if run hit VM_RET return true; if (comprehending) { struct variable *item = (struct variable*)stack_pop(context->operand_stack); array_add(result->list, item); } } } if (comprehending) stack_push(context->operand_stack, result); return false; }
static inline bool vm_trycatch(struct context *context, struct byte_array *program) { struct byte_array *trial = serial_decode_string(program); DEBUGPRINT("TRY %d\n", trial->length); display_code(context, trial); struct byte_array *name = serial_decode_string(program); struct byte_array *catcher = serial_decode_string(program); DEBUGPRINT("%sCATCH %s %d\n", indentation(context), byte_array_to_string(name), catcher->length); display_code(context, catcher); if (!context->runtime) return false; run(context, trial, NULL, true); if (context->vm_exception) { set_named_variable(context, NULL, name, context->vm_exception); context->vm_exception = NULL; return run(context, catcher, NULL, true); } return false; }
char passcode_entering(char *pass, int idle_time) //input: address of array to store passcode, idle time in seconds //returns: 0 if timer interrupt causes exit. KEY_ENTER if 'enter' causes exit. KEY_CHANGE if 'change' causes exit. //reqs: display_code(), PASS_LENGTH, KEY_ENTER, KEY_CHANGE, clock, clock_freq, key_pressed, key_flag. { int entered=0,loop; for(clock=0;clock<(idle_time*clock_freq);) { if(key_flag==1) { if(key_pressed!=KEY_ENTER && key_pressed!=KEY_CHANGE) //key is not "enter" and is not "pass change" { entered++; if(entered>PASS_LENGTH) { //shuffle all codes down the array for(loop=0;loop<PASS_LENGTH;++loop) { pass[loop]=pass[loop+1]; } entered=PASS_LENGTH; } pass[entered-1]=key_pressed; //add data to the pass string display_code(pass,entered); //display the new string while(scan()==1); //wait whilst the key is held key_flag=0; } if(key_pressed==KEY_ENTER) //enter has been pressed. { while(scan()==1); //wait whilst the key is held key_flag=0; return(KEY_ENTER); } if(key_pressed==KEY_CHANGE) //enter has been pressed. { while(scan()==1); //wait whilst the key is held key_flag=0; return(KEY_CHANGE); } } } return(0);//timer caused exit, return 0. }
void display_program(struct byte_array *program) { struct context *context = context_new(false); INDENT DEBUGPRINT("%sprogram bytes:\n", indentation(context)); INDENT for (int i=0; i<program->length; i++) DEBUGPRINT("%s%2d:%3d\n", indentation(context), i, program->data[i]); UNDENT DEBUGPRINT("%sprogram instructions:\n", indentation(context)); byte_array_reset(program); display_code(context, program); UNDENT UNDENT }