[Home]SourceContext

LinuxCNCKnowledgeBase | RecentChanges | PageIndex | Preferences | LinuxCNC.org

Showing revision 1

Introduction of source contexts

The current method of cross-linking motion ids to line numbers is inadaequate. Consequences are:

  1. run-from-line is very limited
  2. no current-source-line feedback in the gui's if external oword subroutines are used
  3. no way to step subroutines
  4. no call stack display

This was acerbated by a problem in motion which let to the introduction of fake line numbers in MDI mode. As a consequence, stepping and source tracking in MDI mode was impossible, as well as some other consistency checks.

Source contexts:

Up to now, we had a fairly simple source context:

Post-introduction we will have a source context for each command which generates a motion (basically everything which travels down the interplist).

Conceptually a unique command origin is identified by a tuple (line number, 'where did it come from').

The 'where did it come from' part is the source context. It consists of:

For ease of handling, a source context is referenced by a unique ID. The interpreter tracks source contexts, and can be queried for the current source context by id through a new method - get_source_context(), which will pass all parts needed to uniquely denote the origin of a motion command:

NML commands put on the interplist so far carried only the line_number.

Now they will also carry source type and context id in the NML_INTERP_LIST_NODE structure (the NML messages themselves remain unchanged). There is no point in tagging every NML command with the source name, and it is a bit bulky. If task needs to know about it, for instance to update emcStatus, it can query the interpreter if the source context id changed.

The cache of source contexts of the interpreter can be cleared explicitly by exexcuting interp.set_source_context(SC_CLEAR, 0, NULL). This would typically happen in task before opening a new file, or running an MDI command.

How GUI's are expected to deal with source contexts:

Current highlight logic

For 'highlight current line' type feedback, GUI's tracked several variables to determine 'where we are':

  1. emcstat.current_line which is the line of the currently executing command in task
  2. emcstat.id which tracks motion's current motion id (motion.traj.id). 0 if currently no motion executing.
  3. emcstat.motion_line which trails motion's current motion id (motion.traj.id)

3) is set from 2) only if > 0, which implies 'if not in MDI mode' in the current line number logic. During MDI commands it remains 0, which stops source highlighting for MDU .

These variables are used for highlight eg here:

from emc_interface.py ca line 481 (used in touchy):

  if self.emcstat.id == 0 and (self.emcstat.interp_state == self.emc.INTERP_PAUSED or self.emcstat.exec_state == self.emc.EXEC_WAITING_FOR_DELAY):
     self.listing.highlight_line(self.emcstat.current_line)
  elif self.emcstat.id == 0:
     self.listing.highlight_line(self.emcstat.motion_line)
  else:
     self.listing.highlight_line(self.emcstat.id or self.emcstat.motion_line)

I understand this is: - if interpreter paused or delaying, highlight the last line read. - if motion is not currently executing a motion, highlight the line which generated the last motion in auto mode. - else hightlight the line which generated the current motion.

New highlight logic

Tracking the source context entails some new state variables:

Motion will have a new pin: motion.source_context_id (s32).

emcStatus will have new fields:

 emcstatus.current_source_context_id 
 emcstatus.current_source_context_type 
 emcstatus.current_source_name

 emcstatus.motion_source_context_id 
 emcstatus.motion_source_context_type
 emcstatus.motion_source_name
 emcstatus.call_level             (this could be used to display the call stack of source locations currently executing.)

These fields are updated within task, through interp.get_source_context(), primarily for consumption by the GUI's.

Displaying the source context:

GUI's are expected to watch the *source_context_id values for changes.

A change of the *context_id means 'display the new source context', for example:

 if id changed:
   retrieve emcstatus.*_source_name depending on logic above
   if *_context_type means 'a string', switch the source window to display the string (this could be multi line).
   if *_context_type means 'a file', switch the source window to open and display the file.
   highlight the line as denoted by *_line.

Displaying the call stack

  1. Track the last source location as well as the current location.
  2. If no last location, set it to current location.
  3. monitor emcstatus.call_level:
    1. if increased, set top of stack to last location, and push the current location.
    2. if decreased, pop top of stack and update top of stack with current location.

Migration:

For now, GUI's may continue to watch current_line, motion_line and id, but will not be able to display different source contexts or the call stack.

To enable source-higliht of MDI, this implies that the negative line number handling in task needs to be removed, which impacts upon the GUIs. If one doesnt want to do the full file/string tracking thing, a small mod of the 'what should I highlight' code should be a workaround. (basically a test for source_context_type == MDI string - then dont display it).

Run-from-Line

The best place to detect a start condition for run-from-line is the interpreter itself. For this purpose, watchpoints will be used (see http://wiki.linuxcnc.org/cgi-bin/wiki.pl?WatchPoints). The interpreter will support several watchpoints, of which 2 are predefined:

- watchpoint zero: run-from-line condition - watchpoint one: pause condition (this adds a new 'run and pause here' option to the GUI's)

The usage pattern in task is as follows:

- for run-from-line say line 7, execute:

  interp.set_watchpoint(0, "this.sequence_number >= 7")
- run the command or file. - examine the watchpoint mask (an interplist attribute which can be retrieved with interp.get_XXX(&watchpoints)) - if the relevant bit (0 for RFL, 1 for pause) has a positive edge for the first time, this sets the start conditon - for pause (bit 1), every positive edge triggers a pause. - at program end or abort, disable the watchpoint with: interp.set_watchpoint(0,0)

Status:


LinuxCNCKnowledgeBase | RecentChanges | PageIndex | Preferences | LinuxCNC.org
This page is read-only. Follow the BasicSteps to edit pages. | View other revisions | View current revision
Edited April 9, 2012 4:56 am by MichaelHaberler (diff)
Search:
Published under a Creative Commons License