6.19.8. Master Frame

There is a _master frame_ for each master document file read by Interscript. It contains data for the document which persists between passes on the source. For example the master table of contents is part of the master frame. Information in the master frame is often collected during pass and set into the frame at the end of the pass so it can be used by the next pass: the table of contents is such an example.

Conceptually, if multiple master documents are processed by interscript, elaboration of each document is performed in a separate thread. The master frame contains thread local data, whereas the process frame is shared by all threads.

At the 'document' level, the failure to generate a document correctly is at most fatal to that thread of control because documents are in some senses independent. However, when multiple documents form a project, inter-document dependencies may dictate abortion of the whole processes if one of the master threads fails.

Start python section to interscript/frames/masterf.py[1 /2 ] Next Last
     1: #line 23 "master_frame.ipk"
     2: from interscript.frames.passf import pass_frame
     3: from interscript.drivers.sources.disk import parse_source_filename
     4: from interscript.languages.interscript_languages import add_translation
     5: import pickle
     6: import types
     7: 
     8: class master_frame:
     9:   "Once per document master frame"
    10:   def _cal_deps(self,t,i):
    11:     #print 'caldeps',i
    12:     n = len(t)
    13:     level0, kind0, filename0, filetime0, changed0, tobuild0 = t[i]
    14:     tobuild0 = changed0
    15:     j=i+1
    16:     while j<n:
    17:       if t[j][0] <= level0: break
    18:       tobuild1, j = self._cal_deps(t,j)
    19:       tobuild0 = tobuild0 or tobuild1
    20:     t[i][5]=tobuild0
    21:     return tobuild0, j
    22: 
    23:   def __init__(self,process,argument_frame):
    24:     self.argument_frame = argument_frame
    25:     self.process = process
    26:     self.site = process.site
    27:     self.platform = process.site.platform
    28: 
    29:     if 'frames' in process.trace:
    30:       self.process.acquire_object(self,'MASTER FRAME')
    31:     for k in argument_frame.__dict__.keys():
    32:       if 'options' in self.process.trace:
    33:         print 'setting MASTER',k,'as',argument_frame.__dict__[k]
    34:       setattr(self,k,argument_frame.__dict__[k])
    35:     self.ids = {}
    36:     self.iflist = []
    37:     self.ftp_list = []
    38:     self.flist = []
    39:     self.fdict = {}
    40:     self.toc = []
    41:     self.include_files = []
    42:     self.classes = {}
    43:     self.functions = {}
    44:     self.sequence_limit = -1
    45:     self.section_index = {}
    46:     self.tests = {}
    47:     self.noticedict = {}
    48:     self.persistent_frames = {}
    49:     self.cache_age = 1 # very old :-)
    50:     os = self.platform.os
    51:     if self.usecache:
    52:       self.cache_name =self.platform.map_filename(
    53:         self.source_prefix, self.filename+'.cache')
    54:       try:
    55:         if 'cache' in self.process.trace:
    56:           print 'CACHE NAME=',self.cache_name
    57:         cache = self.platform.open(self.cache_name,'r')
    58:         if 'cache' in self.process.trace:
    59:           print 'CACHE FILE OPENED'
    60:         self.persistent_frames = pickle.load(cache)
    61:         cache.close()
    62:         if 'cache' in self.process.trace:
    63:           print 'GOT CACHE'
    64:         self.cache_age = self.platform.getmtime(self.cache_name)
    65:         if 'cache' in self.process.trace:
    66:           print 'AGE=',self.cache_age
    67:           self.dump_cache()
    68:         del cache
    69:       except KeyboardInterrupt: raise
    70:       except:
    71:         if 'cache' in self.process.trace:
    72:           print 'UNABLE TO LOAD CACHE'
    73: 
    74:     include_files = self.persistent_frames.get('include files',[])
    75:     old_options = self.persistent_frames.get('options',{})
    76: 
    77:     self.src_tree = []
    78:     for level, kind, filename in include_files:
    79:       f = self.platform.map_filename(self.source_prefix, filename)
    80:       filetime = self.platform.getmtime(f)
    81:       changed = filetime > self.cache_age
    82:       self.src_tree.append([level, kind, filename, filetime, changed, -1])
    83: 
    84:     if 'deps' in self.process.trace:
    85:       print 'SOURCE FILE CHANGE STATUS DEPENDENCIES'
    86:       print 'CACHE TIME=',self.cache_age
    87:       self.dump_entry(self.src_tree,0)
    88:       print
    89: 
    90:     src_tree_changed = 1
    91:     dummy = 0
    92:     if len(self.src_tree)>0:
    93:       src_tree_changed, dummy = self._cal_deps(self.src_tree,0)
    94:     del dummy
    95: 
    96:     if 'deps' in self.process.trace:
    97:       print 'COMPUTED DEPENDENCIES'
    98:       print 'CACHE TIME=',self.cache_age,
    99:       self.dump_entry(self.src_tree,0)
   100:       print
   101:       if src_tree_changed:
   102:         print 'WORK TO BE DONE'
   103:         for level, kind, filename, filetime, changed, tobuild in self.src_tree:
   104:           if changed: print kind,'file',filename,'CHANGED'
   105:         for level, kind, filename, filetime, changed, tobuild in self.src_tree:
   106:           if tobuild: print kind,'file',filename,'WILL BE REBUILT'
   107:         for level, kind, filename, filetime, changed, tobuild in self.src_tree:
   108:           if not tobuild: print kind,'file',filename,'WILL BE SKIPPED'
   109:       else:
   110:         print 'NO FILES CHANGED'
   111:         if self.autoweave:
   112:           print 'WEAVING ENABLED'
   113:         else: print 'NO WEAVING'
   114: 
   115:     if src_tree_changed:
   116:       skiplist = []
   117:       for level, kind, filename, filetime, changed, tobuild in self.src_tree:
   118:         if not tobuild:
   119:           skiplist.append((level, kind, filename))
   120:     current_options = self.argument_frame.__dict__
   121: 
   122:     ign_opt = ['trace','passes']
   123:     cur_opt = current_options.copy()
   124:     old_opt = old_options.copy()
   125:     for key in cur_opt.keys():
   126:       if key in ign_opt: del cur_opt[key]
   127:     for key in old_opt.keys():
   128:       if key in ign_opt: del old_opt[key]
   129: 
   130:     options_changed = old_opt != cur_opt
   131:     del ign_opt, cur_opt, old_opt
   132: 
   133:     old_converged = self.persistent_frames.get('converged',0)
   134:     if 'deps' in self.process.trace:
   135:       if old_converged:
   136:         print 'PREVIOUS RUN CONVERGED'
   137:       else:
   138:         print 'PREVIOUS RUN DID NOT CONVERGE'
   139:       if options_changed:
   140:         print 'OPTIONS CHANGED'
   141:       else:
   142:         print 'SAME OPTIONS AS BEFORE'
   143: 
   144:     if (not options_changed) and old_converged and (not src_tree_changed):
   145:       print 'NO WORK TO DO, returning'
   146:       return
   147: 
   148:     old_skiplist = self.persistent_frames.get('skiplist',[])
   149:     if options_changed:
   150:       print 'PROCESSING WHOLE FILE (options changed)'
   151:       skiplist = []
   152:     elif self.autoweave:
   153:       print 'PROCESSING WHOLE FILE (incremental weaving not supported yet)'
   154:       skiplist = []
   155:     else:
   156:       if old_converged:
   157:         print 'SKIPPING (newly changed files)'
   158:         for sig in skiplist:
   159:           print ' ',sig
   160:       else:
   161:         if src_tree_changed:
   162:           print 'PROCESSING WHOLE FILE (source changed)'
   163:           skiplist = []
   164:         else:
   165:           print 'SKIPPING (files skipped last run, which did not converge)'
   166:           skiplist = old_skiplist
   167:     self.run_passes(skiplist)
   168:     self.persistent_frames['skiplist']=skiplist
   169:     return
   170: 
End python section to interscript/frames/masterf.py[1]


6.19.8.1. Run the passes