def _render(self): """ Internal render method for the state printer. """ # We rebind print to print to our StringIO instance for the scope of # this method. prn = partial(print, file=self.sio) def print_binding(print_fn, b): print_fn('{}{} = {}'.format(name_repr(b), self.loc_image(b.gen_name), self.value_image(b.gen_name))) if self.state is None: prn('Selected frame is not in a property.') return # If we are asked to display only one variable, look for it, print it, # and stop there. if self.var_name: for scope_state in self.state.scopes: for b in scope_state.bindings: if b.dsl_name == self.var_name: print_binding(prn, b) return prn('No binding called {}'.format(self.var_name)) return prn('Running {}'.format(prop_repr(self.state.property))) if self.state.property.dsl_sloc: prn('from {}'.format(self.state.property.dsl_sloc)) if self.state.in_memoization_lookup: prn('About to return a memoized result...') for scope_state in self.state.scopes: is_first = [True] def print_info(strn): if is_first[0]: prn('') is_first[0] = False prn(strn) for b in scope_state.bindings: print_binding(print_info, b) done_exprs, last_started = scope_state.sorted_expressions() for e in done_exprs: print_info('{}{} -> {}'.format(expr_repr(e), self.loc_image(e.result_var), self.value_image(e.result_var))) if last_started: print_info('Currently evaluating {}'.format( expr_repr(last_started))) if last_started.dsl_sloc: print_info('from {}'.format(last_started.dsl_sloc))
def go_out(context: Context) -> None: """ Continue execution until the end of the evaluation of the current sub-expression. """ # Look for the expression that is being evaluated currently state = context.decode_state() if state is None: print('Selected frame is not in a property.') return scope_state, current_expr = state.lookup_current_expr() if not current_expr: print('Not evaluating any expression currently') return assert scope_state is not None # Look for the point in the generated library where its evaluation will be # done. until_line_no = None for e in scope_state.scope.events: if isinstance(e, ExprDone) and e.expr_id == current_expr.expr_id: until_line_no = e.line_no if until_line_no is None: print('ERROR: cannot find the end of evaluation for expression {}.' ' Code generation may have a bug.'.format(current_expr)) return # Now go there! When we land in the expected place, also be useful and # display the value we got. gdb.execute('until {}'.format(until_line_no)) frame = gdb.selected_frame() new_state = context.decode_state(frame) assert new_state is not None new_expr = new_state.lookup_expr(current_expr.expr_id) if new_state: _, new_current_expr = new_state.lookup_current_expr() else: new_current_expr = None # Do some sanity checks first... def error(msg: str) -> None: print('ERROR: {}: something went wrong...'.format(msg)) if new_state is None or new_state.property != state.property: return error('we landed in another property') if new_expr is None: return error('cannot find back the same expression') if not new_expr.is_done: return error('the expression is not evaluated yet') print('') print('{} evaluated to: {}'.format(expr_repr(current_expr), new_expr.read(new_state.frame))) if new_current_expr: print('') print('Now evaluating {}'.format(expr_repr(new_current_expr)))
def go_next(context): """ Continue execution until reaching another expression. """ state = context.decode_state() if not state: print('Selected frame is not in a property.') return # If execution reached the part of the code where the property is about to # return a cached result, just let it return. if state.in_memoization_lookup: gdb.execute('finish') return scope_state, current_expr = state.lookup_current_expr() if current_expr is None: # There are only two possible causes for no currently evaluating # expressions: either the property just started (root expression # evaluation is ahead), either it is about to return (root expr. eval. # is behind). bp_group = break_scope_start(context, state.property_scope.scope, from_line_no=state.line_no) if bp_group: # The first expression is ahead: resume execution until we reach # it. gdb.execute('continue') else: gdb.execute('finish') else: # Depending on the control flow behavior of the currently running # expression, the next step can be either its parent expression or any # of its sub-expressions. next_slocs_candidates = [] # First look for the point where the current expression terminates its # evaluation. next_slocs_candidates.append(current_expr.done_event.line_no) # Now look for the starting point for all sub-expressions for subexpr in current_expr.start_event.sub_expr_start: next_slocs_candidates.append(subexpr.line_no) BreakpointGroup(context, next_slocs_candidates) gdb.execute('continue') new_current_expr = None new_expr = None new_state = context.decode_state() if new_state: _, new_current_expr = new_state.lookup_current_expr() if current_expr: new_expr = new_state.lookup_expr(current_expr.expr_id) # If we just finished the evaluation of an expression, display its value if new_expr and new_expr.is_done: print('{} evaluated to {}'.format(expr_repr(new_expr), new_expr.read(new_state.frame))) # Display the expression of most interest, if any if new_current_expr: print('') print('Now evaluating {}'.format(expr_repr(new_current_expr)))