diff m-toolbox/classes/@LTPDAworkbench/parseBlocks.m @ 0:f0afece42f48

Import.
author Daniele Nicolodi <nicolodi@science.unitn.it>
date Wed, 23 Nov 2011 19:22:13 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/m-toolbox/classes/@LTPDAworkbench/parseBlocks.m	Wed Nov 23 19:22:13 2011 +0100
@@ -0,0 +1,459 @@
+function [cmds, rbs] = parseBlocks(blocks, wb, varID)
+  
+  cmds = {};
+  rbs = [];
+  Nrbs = awtinvoke(blocks, 'size');
+  
+  
+  % loop over blocks
+  for jj=1:Nrbs
+    block = awtinvoke(blocks, 'get', jj-1);
+    
+    if ~block.isCommentedOut
+      rbs = [rbs block];
+      bname = char(block.getName);
+      %     if  exist(bname) > 1 || ~isvarname(bname)
+      %       error('The block named "%s" is not a valid variable name. \nPlease rename it.', bname);
+      %     end
+      
+      % if this is a MATBlock we treat it differently since it has
+      % no plist.
+      if isa(block, 'mpipeline.canvas.MATBlock')
+        
+        cmds = parseMATblock(cmds, block, varID);
+        
+      elseif isa(block, 'mpipeline.canvas.PipelineBlock')
+        
+        cmds = parsePipelineBlock(cmds, block, varID);
+        
+      elseif isa(block, 'mpipeline.canvas.MATfcn')
+        
+        cmds = parseMATfcn(cmds, block, varID);
+        
+      elseif isa(block, 'mpipeline.canvas.MTerminal')
+        % Terminals are not executed. They are skipped over when asking
+        % for source and child blocks; that's handled on the java side.
+      elseif isa(block, 'mpipeline.canvas.MConstant')
+        % Don't do anything, we did this at the beginning of
+        % execution
+      elseif isa(block, 'mpipeline.canvas.Mux')
+        
+        cmds = parseMux(cmds, block, varID);
+        
+      elseif isa(block, 'mpipeline.canvas.Demux')
+        
+        cmds = parseDemux(cmds, block, varID);
+        
+      elseif isa(block, 'mpipeline.canvas.ToWorkspace')
+        
+        cmds = parseToWorkspace(cmds, block, varID);
+        
+      else
+        
+        cmds = parseLTPDAblock(cmds, block, wb, varID);
+        
+      end % End if on block type
+    end % End if block commented out
+  end % End loop over blocks
+end
+
+
+%--------------------------------------------------------------------------
+% Parse a ToWorkspace block
+%
+function cmds = parseToWorkspace(cmds, block, varID)
+  
+  % loop over inputs to make input vars
+  inputs = block.getInputs();
+  
+  % Loop over the inputs to get the variable names of the inputs
+  for kk=0:inputs.size()-1
+    ip = inputs.get(kk);
+    % get the block which is connected to this input
+    srcblock = block.getSourceBlock(ip.getNumber);
+    % get the port number at the source block
+    srcportNumber = block.getSourceBlockPortNumber(ip.getNumber);
+    if ~isempty(srcblock)
+      varname = LTPDAworkbench.getWS_VarName(varID, srcblock, srcportNumber);
+      
+      % get class of the object
+      cl = evalin('base', [ 'class(' varname ')']);
+      
+      % get new var name
+      %   - this means split the outvar at the last '.'
+      nv = getVar(varname);
+      
+      if ismember(cl, utils.helper.ltpda_userclasses)
+        cmd  = [nv ' = copy(' varname ',1);'];
+      else
+        cmd  = [nv ' = ' varname ';'];
+      end
+      
+      cmds = [cmds {cmd}];
+    end
+  end
+  
+  assignin('base', 'cmds', cmds);
+  clear();
+  cmds = evalin('base', 'cmds');
+  
+end
+
+
+function nv = getVar(ov)
+  
+  nv = '';
+  
+  for kk=length(ov):-1:1
+    if ov(kk) == '.'
+      break
+    else
+      nv = [nv ov(kk)];
+    end
+  end
+  
+  nv = nv(end:-1:1);
+  
+end
+
+%--------------------------------------------------------------------------
+% Parse a Demux block
+%
+function cmds = parseDemux(cmds, block, varID)
+  
+  % loop over inputs to make input vars
+  inputs = block.getInputs();
+  
+  % Demux has one input
+  ip = inputs.get(0);
+  % get the block which is connected to this input
+  srcblock = block.getSourceBlock(ip.getNumber);
+  % get the port number at the source block
+  srcportNumber = block.getSourceBlockPortNumber(ip.getNumber);
+  if ~isempty(srcblock)
+    varname = LTPDAworkbench.getWS_VarName(varID, srcblock, srcportNumber);
+    incmd = [varname];
+  end
+  
+  % make output vars
+  outputs = block.getOutputs();
+  for kk=1:outputs.size()
+    outvar = LTPDAworkbench.getWS_VarName(varID, block, kk-1);
+    cmds = [cmds {[outvar ' = ' incmd '(' num2str(kk) ');']}];
+  end
+  
+  
+end
+
+%--------------------------------------------------------------------------
+% Parse a Mux block
+%
+function cmds = parseMux(cmds, block, varID)
+  
+  % loop over inputs to make input vars
+  inputs = block.getInputs();
+  incmd = '[';
+  varnames = {};
+  
+  % Loop over the inputs to get the variable names of the inputs
+  for kk=0:inputs.size()-1
+    ip = inputs.get(kk);
+    % get the block which is connected to this input
+    srcblock = block.getSourceBlock(ip.getNumber);
+    % get the port number at the source block
+    srcportNumber = block.getSourceBlockPortNumber(ip.getNumber);
+    if ~isempty(srcblock)
+      varname = LTPDAworkbench.getWS_VarName(varID, srcblock, srcportNumber);
+      varnames = [varnames {varname}];
+      incmd = [incmd varname ','];
+    end
+  end
+  if incmd(end)==','
+    incmd = incmd(1:end-1);
+  end
+  incmd = strtrim(incmd);
+  incmd = [incmd ']'];
+  % make output vars
+  outputs = block.getOutputs();
+  if outputs.size() > 1
+    error('### Mux blocks should have only one output.');
+  elseif outputs.size() == 1
+    outcmd = '[';
+    for kk=1:outputs.size()
+      outvar = LTPDAworkbench.getWS_VarName(varID, block, kk-1);
+      outcmd = [outcmd outvar ' '];
+    end
+    outcmd = strtrim(outcmd);
+    outcmd = [outcmd '] = '];
+  else
+    outcmd = '';
+  end
+  
+  cmds = [cmds {[outcmd incmd ';']}];
+  
+  
+end
+
+
+%--------------------------------------------------------------------------
+% Parse a command from a MATBlock block
+%
+function cmds = parsePipelineBlock(cmds, block, varID)
+  
+  % get variable name
+  outvar = LTPDAworkbench.getWS_VarName(varID, block, 0);
+  
+  % Get source port that this block links to
+  sp = block.getSourcePort;
+  % get the parent of that port
+  sb = sp.getParent;
+  % get var name
+  srcvar = LTPDAworkbench.getWS_VarName(varID, sb, sp.getNumber);
+  
+  % build command string
+  cmd = [outvar ' = ' srcvar ';'];
+  
+  % we should check if the srcvar exists
+  try
+    evalin('base', [srcvar ';']);
+  catch
+    utils.helper.errorDlg(sprintf('Source variable [%s] doesn''t exist. Did you run the required pipeline?', srcvar), 'Pipeline Source Error');
+  end
+  
+  cmds = [cmds {cmd}];
+  
+end
+
+
+%--------------------------------------------------------------------------
+% Parse a command from a MATBlock block
+%
+function cmds = parseMATblock(cmds, block, varID)
+  
+  % get variable name
+  outvar = LTPDAworkbench.getWS_VarName(varID, block, 0);
+  % get expression
+  exp = char(block.getExpression());
+  
+  % can this expression be evaluated or is it a string?
+  try
+    evalin('base', [exp ';']);
+    cmd = [outvar ' = ' exp ';'];
+  catch
+    cmd = [outvar ' = ''' exp ''';'];
+  end
+  cmds = [cmds {cmd}];
+  
+end
+
+
+%--------------------------------------------------------------------------
+% Parse a command from an LTPDA block
+%
+function cmds = parseLTPDAblock(cmds, block, wb, varID)
+  
+  % We have a normal LTPDA block with a plist etc....
+  
+  blockclass = char(block.getMinfo().getMclass);
+  % build command
+  cmd = strrep(char(block.getAlgoName), ' ', '_');
+  
+  % make plist for this block
+  jpl = block.getPlist();
+  pl = LTPDAworkbench.jpl2mpl(jpl);
+  spl = string(pl);
+  
+  % We need to skip any PORT_# when making the inputs
+  tks = regexpi(spl, 'PORT_(\d+)', 'tokens');
+  skipports = [];
+  for kk=1:numel(tks)
+    skipports = [skipports str2double(tks{kk}{1})];
+  end
+  %       skipports = skipports + 1;
+  % loop over inputs to make input vars
+  inputs = block.getInputs();
+  incmd = '(';
+  varnames = {};
+  
+  % Loop over the inputs to get the variable names of the inputs
+  for kk=0:inputs.size()-1
+    ip = inputs.get(kk);
+    if ~any(ip.getNumber==skipports)
+      % get the block which is connected to this input
+      srcblock = block.getSourceBlock(ip.getNumber);
+      % get the port number at the source block
+      srcportNumber = block.getSourceBlockPortNumber(ip.getNumber);
+      if ~isempty(srcblock)
+        varname = LTPDAworkbench.getWS_VarName(varID, srcblock, srcportNumber);
+        varnames = [varnames {varname}];
+        incmd = [incmd varname ','];
+      end
+    end
+  end
+  incmd = strtrim(incmd);
+  incmd = [incmd spl ')'];
+  % make output vars
+  outputs = block.getOutputs();
+  if outputs.size() > 0
+    outcmd = '[';
+    for kk=1:outputs.size()
+      output = outputs.get(kk-1);
+      outvar = LTPDAworkbench.getWS_VarName(varID, block, output.getNumber);
+      bits = regexp(outvar, '\.', 'split');
+      if  exist(outvar) > 1 && ~allAreVarNames(bits)
+        error('The block named "%s" is not a valid variable name. \nPlease rename it.', outvar);
+      end
+      outcmd = [outcmd outvar ' '];
+    end
+    outcmd = strtrim(outcmd);
+    outcmd = [outcmd '] = '];
+  else
+    outcmd = '';
+  end
+  
+  % Modify plist constructors looking for PORT_#
+  for kk=1:pl.nparams
+    if ischar(pl.params(kk).getVal)
+      idxs = regexpi(pl.params(kk).getVal, '(PORT_\d*)', 'tokens');
+      repstr = pl.params(kk).getVal;
+      for ii=1:numel(idxs)
+        pstr = idxs{ii}{1};
+        % get port number
+        [s,r] = strtok(pstr, '_');
+        portNumber = str2num(r(2:end));
+        % Now we need to find the name of the output variable at the
+        % other end of this pipe
+        sb = block.getSourceBlock(portNumber);
+        if ~isa(sb, 'mpipeline.canvas.MElementWithPorts')
+          error('### Block %s has an input PORT_%d specified in the plist, \nbut the block has no such input, or the input is not connected to a source block', char(block.getName()), portNumber);
+        end
+        sbp = block.getSourceBlockPortNumber(portNumber);
+        sbpn = LTPDAworkbench.getWS_VarName(varID, sb, sbp);
+        % replace the PORT_# string with the correct variable name
+        repstr = strrep(repstr, pstr, char(sbpn));
+      end
+      % If we modified the parameter value string, then we need to
+      % remove the string quotes, and replace this in the string
+      % representation of the plist (spl)
+      if ~strcmp(repstr, pl.params(kk).getVal)
+        repstr = strrep(repstr, '''', '');
+        spl = strrep(spl, ['''' pl.params(kk).getVal ''''], repstr);
+      end
+      
+      % rebuild incmd
+      incmd = '(';
+      for ll=1:numel(varnames)
+        incmd = [incmd varnames{ll} ','];
+      end
+      incmd = strtrim(incmd);
+      incmd = [incmd spl ')'];
+    end
+  end
+  comment = ['% ' blockclass];
+  
+  % We do something different if this is a modifier
+  if block.isModifier
+    
+    mcmd = [cmd incmd ';' comment];
+    if outputs.size() > 1
+      error('Block %s is set as a modifier but has more than one output. This is not possible.', char(block.getName));
+    end
+    cmds = [cmds {mcmd}];
+    for kk=1:numel(varnames)
+      ecmd = [outvar '(' num2str(kk) ') = ' varnames{kk} ';'];
+      cmds = [cmds {ecmd}];
+    end
+    
+  else
+    cmds = [cmds {[outcmd cmd incmd ';' comment]}];
+  end
+  
+  % add command to set name of block if this is a constructor
+  cat = char(block.getMinfo.getMcategory);
+  if outputs.size() == 1 && strcmpi(cat, 'constructor') && (strcmpi(pl.find('name'), 'None') || isempty(pl.find('name')))
+    cmd = {[outvar '.setName(''' char(block.getName()) ''')']};
+    cmds = [cmds cmd];
+  end
+  
+  % add command to attach workbench if necessary
+  if block.isAttachWorkbench
+    
+    % get the workbench in XML format
+    if isa(wb, 'LTPDAworkbench')
+      xmlout = char(wb.mp.workbenchAsXMLString);
+    end
+    
+    for kk=1:outputs.size()
+      outvar = LTPDAworkbench.getWS_VarName(varID, block, kk-1);
+      bits = regexp(outvar, '\.', 'split');
+      if  exist(outvar) > 1 && ~allAreVarNames(bits)
+        error('The block named "%s" is not a valid variable name. \nPlease rename it.', outvar);
+      end
+      cmd = {[outvar '.setMdlfile('''  strrep(xmlout, '''', '''''') ''');']};
+      cmds = [cmds cmd];
+    end
+    
+  end
+  
+end
+
+function res = allAreVarNames(cs)
+  
+  res = true;
+  for jj=1:numel(cs)
+    if ~isvarname(cs{jj})
+      res = false;
+      break;
+    end
+  end
+  
+end
+
+%--------------------------------------------------------------------------
+% Parse a command from a MATfcn block
+%
+function cmds = parseMATfcn(cmds, block, varID)
+  
+  % build command
+  cmd = char(block.getFcnName);
+  
+  % loop over inputs to make input vars
+  inputs = block.getInputs();
+  incmd = '(';
+  varnames = {};
+  
+  % Loop over the inputs to get the variable names of the inputs
+  for kk=0:inputs.size()-1
+    ip = inputs.get(kk);
+    % get the block which is connected to this input
+    srcblock = block.getSourceBlock(ip.getNumber);
+    % get the port number at the source block
+    srcportNumber = block.getSourceBlockPortNumber(ip.getNumber);
+    if ~isempty(srcblock)
+      varname = LTPDAworkbench.getWS_VarName(varID, srcblock, srcportNumber);
+      varnames = [varnames {varname}];
+      incmd = [incmd varname ','];
+    end
+  end
+  if incmd(end)==','
+    incmd = incmd(1:end-1);
+  end
+  incmd = strtrim(incmd);
+  incmd = [incmd ')'];
+  % make output vars
+  outputs = block.getOutputs();
+  if outputs.size() > 0
+    outcmd = '[';
+    for kk=1:outputs.size()
+      outvar = LTPDAworkbench.getWS_VarName(varID, block, kk-1);
+      outcmd = [outcmd outvar ' '];
+    end
+    outcmd = strtrim(outcmd);
+    outcmd = [outcmd '] = '];
+  else
+    outcmd = '';
+  end
+  
+  cmds = [cmds {[outcmd cmd incmd ';']}];
+end
+