Commits

Brett Giles committed 2e2c640

All methods flog 20 or less.

Enough for now - may revisit big classes (e.g., main screen) at some other time.

Comments (0)

Files changed (43)

GUI/spec/controller/classical_stack_controller_spec.rb

     @c = ClassicalStackController.instance
   end
   it "should raise an error when created with junk" do
-    expect { @c.set_classical_stack_data("junk")}. to raise_error   ModelCreateError, /junk/
+    expect { @c.set_classical_stack_data("junk")}. to raise_error   ParserError, /junk/
   end
 
   it "should create a classical stack when given the correct input" do

GUI/spec/model/descriptor_model_spec.rb

 describe ClassicalDescriptorModel do
   it  "should raise an error if constructed with something other than <Classical>list of ints or bools</Classical>" do
     expect {
-      sc = AbstractDescriptorModel.make_instance "<Classicalk>err</Classical>"
+      sc = AbstractDescriptorModel.make_instance "<Classical>err</Classical>"
     }.to raise_error(ParserError, /<Classical>err<\/Classical>/)
   end
   it  "should have a length equal to the number of elements of the passed in list" do

GUI/spec/model/dump_model_spec.rb

 describe DumpSplitModel do
   it "should just accept and display the text of the split" do
     ds = DumpSplitModel.new( "<DumpSplit>whatever</DumpSplit>")
-    ds.text.should == "<DumpSplit>whatever</DumpSplit>"
+    ds.text.should == "whatever"
   end
 end
 

GUI/spec/model/quantum_stack_model_spec.rb

 
 
 describe QuantumStackModel do
-
-
-  describe "class method get_next_qstack" do
-    it "should return a nil when given the empty string" do
-      qsp = QuantumStackModel::get_next_qstack("")
-      qsp.should be_nil
-    end
-    it "should return a pair of the qstack and empty string when only given only one" do
-      qsp = QuantumStackModel::get_next_qstack(QSVAL5)
-      qsp[0].should == QSVAL5
-      qsp[1].should == ""
-    end
-    it "should return a pair of the qstack and empty string when only given only bottom" do
-      qsp = QuantumStackModel::get_next_qstack("<bottom/>")
-      qsp[0].should == "<bottom/>"
-      qsp[1].should == ""
-    end
-    it "should return a pair of the qstack and bottom string when only given two bottoms" do
-      qsp = QuantumStackModel::get_next_qstack("<bottom/><bottom/>")
-      qsp[0].should == "<bottom/>"
-      qsp[1].should == "<bottom/>"
-    end
-    it "should return the first, then the second when given two and the second call is on the remainder" do
-      qsp = QuantumStackModel::get_next_qstack(QSVAL5+QSVAL5)
-      qsp[0].should == QSVAL5
-      qsp[1].should == QSVAL5
-      qsp2 = QuantumStackModel::get_next_qstack(qsp[1])
-      qsp2[0].should == QSVAL5
-      qsp2[1].should == ""
-    end
-
-    it "should return the first, then the second when when given two stacks with more substacks" do
-      qsp = QuantumStackModel::get_next_qstack(QSQBHAD+QSQBHAD)
-      qsp[0].should == QSQBHAD
-      qsp[1].should == QSQBHAD
-      qsp2 = QuantumStackModel::get_next_qstack(qsp[1])
-      qsp2[0].should == QSQBHAD
-      qsp2[1].should == ""
-    end
-  end
-  describe "class method multiple stacks" do
-    before(:each) do
-      @st=double("StackTranslation", :reverse_lookup => "p", :nil? => false)
-    end
-    it "should create an empty array for no input" do
-      rv  = QuantumStackModel::make_multiple_stacks("",@st)
-      rv.length.should == 0
-    end
-    it "should create a one element array for one" do
-      rv = QuantumStackModel::make_multiple_stacks(""+QSVAL5+"",@st)
-      rv.length.should == 1
-    end
-    it "should create an n element array for n copies" do
-      [2,3,4,5,6].each do |i|
-        rv = QuantumStackModel::make_multiple_stacks((""+QSVAL5+"")*i,@st)
-        rv.length.should == i
-      end
-    end
-  end
   describe "instance setup" do
     before(:each) do
       @qs=QuantumStackModel.new
     it "should give an invalid create error when created with incorrect data" do
       expect {
         @qs.quantum_stack = "err"
-      }.to raise_error ModelCreateError, /err/
+      }.to raise_error ParserError, /err/
     end
     it "should give an error when stackzero has substacks" do
       expect {

GUI/spec/parsers/abstract_pattern_parser_spec.rb

       AbstractPatternParser.new "whatever"
     }.to raise_error ParserError, /whatever/
   end
+  describe "class methods" do
+    describe "surround_with_start_end" do
+      it "when given the regexp 'ab' gives a regexp that only parses 'ab' " do
+        AbstractPatternParser::surround_with_start_end(/ab/).should =~ 'ab'
+      end
+      it "when given the regexp 'ab' gives a regexp that will not  parses 'xaby' " do
+        AbstractPatternParser::surround_with_start_end(/ab/).should_not =~ 'xaby'
+      end
+    end
+  end
+      
 end

GUI/spec/parsers/dump_call_parser_spec.rb

+require 'spec/spec_helper'
+
+require 'spec/specdata/dump_data'
+
+describe DumpCallParser do
+  it "should successfully parse a call with no entries in the classical stack" do
+    p = DumpCallParser.new DCALL
+    p.parsed?.should be_true
+  end
+  it "should successfully parse a call with 1 entry in the classical stack" do
+    p = DumpCallParser.new DCALL1
+    p.parsed?.should be_true
+  end
+  
+  it "should successfully parse a call with 2 entries in the classical stack" do
+    p = DumpCallParser.new DCALL2
+    p.parsed?.should be_true
+  end
+  it "should give a parse error if the int is missing" do
+    expect {
+      DumpCallParser.new "<DumpCall><string>Ret</string><Classical></Classical></DumpCall>"
+    }.to raise_error ParserError, /DumpCall/
+  end
+  
+  it "should give a parse error if the return string is missing" do
+    expect {
+      DumpCallParser.new "<DumpCall><int>5</int><Classical></Classical></DumpCall>"
+    }.to raise_error ParserError, /DumpCall/
+  end
+  
+  it "should give a parse error if the classical stack is missing" do
+    expect {
+      DumpCallParser.new "<DumpCall><int>5</int><string>Ret</string></DumpCall>"
+    }.to raise_error ParserError, /DumpCall/
+  end
+  it "should give a parse error if the classical stack is incorrect" do
+    expect {
+      DumpCallParser.new "<DumpCall><int>5</int><string>Ret</string><Classical>junk</Classical></DumpCall>"
+    }.to raise_error ParserError, /DumpCall/
+  end
+end
+  

GUI/spec/parsers/dump_parser_spec.rb

+require 'spec/spec_helper'
+
+require 'spec/specdata/dump_data'
+
+describe DumpParser do
+  it "should parse a single call dump" do
+    dcp = DumpParser.new DUMPSINGLECALL
+    dcp.parsed?.should be_true
+  end
+  it "should parse a single split dump" do
+    dcp = DumpParser.new DUMPSPLIT
+    dcp.parsed?.should be_true
+  end
+  it "should parse a list of call dump" do
+    dcp = DumpParser.new DUMPTWOCALL
+    dcp.parsed?.should be_true
+  end
+  it "should parse a mixed list of call and split dump" do
+    dcp = DumpParser.new DUMPCALLSPLITCALL
+    dcp.parsed?.should be_true
+  end
+end

GUI/spec/parsers/dump_split_parser_spec.rb

+require 'spec/spec_helper'
+
+
+describe DumpSplitParser do
+  it "should successfully parse  '<DumpSplit>1.0</DumpSplit>'" do
+    p = DumpSplitParser.new "<DumpSplit>1.0</DumpSplit>"
+    p.parsed?.should be_true
+  end
+  
+  it "should successfully parse  '<DumpSplit>whatever</DumpSplit>'" do
+    p = DumpSplitParser.new "<DumpSplit>whatever</DumpSplit>"
+    p.parsed?.should be_true
+  end
+  it "should successfully parse  '<DumpSplit>what<DumpSplit>whatever</DumpSplit>ever</DumpSplit>'" do
+    p = DumpSplitParser.new "<DumpSplit>what<DumpSplit>whatever</DumpSplit>ever</DumpSplit>"
+    p.parsed?.should be_true
+  end
+  it "should parse  '<DumpSplit>what<DumpSplit>whatever</DumpSplit>ever</DumpSplit>' as 'what<DumpSplit>whatever</DumpSplit>ever'" do
+    p = DumpSplitParser.new "<DumpSplit>what<DumpSplit>whatever</DumpSplit>ever</DumpSplit>"
+    p.parsed_value.should == "what<DumpSplit>whatever</DumpSplit>ever"
+  end
+end

GUI/spec/parsers/quantum_stack_parser_spec.rb

+require 'spec/spec_helper'
+
+require 'spec/specdata/quantum_stack_data'
+
+
+describe QuantumStackParser do
+  describe "multiple substack layers" do
+    it "should correctly parse an item with no substacks" do
+      q = QuantumStackParser.new QSVAL5
+      q.substacks.length.should == 0
+    end
+    
+    it "should correctly parse an item with one layer of substacks" do
+      q = QuantumStackParser.new QSINT
+      q.substacks.length.should == 2
+      q.substacks[0].substacks.length.should == 0
+    end
+    
+    it "should correctly parse an item with multi layers of substacks" do
+      q = QuantumStackParser.new QS3LEVEL
+      q.substacks.length.should == 3
+      q.substacks[2].substacks.length.should == 1
+      q.substacks[2].substacks[0].substacks.length.should == 0
+    end
+  end
+  
+  describe "bottom stacks" do
+    it "should return a bottom=true for '<bottom/>'" do
+      q = QuantumStackParser.new "<bottom/>"
+      q.bottom?.should be_true
+    end
+    BOTTOMS.each do |b|
+      it "parses  stack with bottom" do
+        q = QuantumStackParser.new b
+        q.parsed?.should be_true
+      end
+      it "returns a single 'bottom' qs for the substacks of these" do
+        q = QuantumStackParser.new b
+        q.substacks[0].bottom?.should be_true
+      end
+    end
+  end
+  describe "stackaddress" do
+    ADDRESSES.each do |m|
+      it "should return #{m[0]} for the stack address" do
+        q = QuantumStackParser.new m[1]
+        q.stackaddress.should == m[0]
+      end
+    end
+  end
+  describe "diagonal" do
+    DIAGS.each do |d|
+      it "should return #{d[0]} for the on_diagonal" do
+        q=QuantumStackParser.new d[1]
+        q.on_diagonal?.should == d[0]
+      end
+    end
+  end
+  describe "descriptors" do
+    it "should return '<Zero/> for a zero descriptor" do
+      q = QuantumStackParser.new QSZ
+      q.descriptor.should == "<Zero/>"
+    end
+    it "should return '<Value>... for a Value descriptor" do
+      q = QuantumStackParser.new QSVAL5
+      q.descriptor.should == "<Value><number>0.5</number></Value>"
+    end
+    it "should return '<Alg...' for a data descriptor" do
+      q = QuantumStackParser.new AL1WITHBOTTOM
+      q.descriptor.should == "<AlgebraicData><string>Nil</string><StackAddresses></StackAddresses></AlgebraicData>"
+    end
+    it "should return '<Class...' for a classical descriptor" do
+      q = QuantumStackParser.new C1WITHBOTTOM
+      q.descriptor.should == "<Classical><cint>27</cint></Classical>"
+    end
+    it "should return '<Qub...' for a qubit descriptor" do
+      q = QuantumStackParser.new QSQBZero
+      q.descriptor.should == "<Qubits><pair><qz/><qz/></pair></Qubits>"
+    end
+  end
+end
+    
+  

GUI/spec/specdata/dump_data.rb

 require 'spec/specdata/classical_stack_data'
 
 DCALL="<DumpCall><int>5</int><string>Ret</string><Classical></Classical></DumpCall>"
-DCALL2="<DumpCall><int>7</int><string>some_method</string><Classical><cint>5</cint></Classical></DumpCall>"
+DCALL1="<DumpCall><int>7</int><string>some_method</string><Classical><cint>5</cint></Classical></DumpCall>"
+DCALL2="<DumpCall><int>7</int><string>some_method</string><Classical><cint>5</cint><cbool>True</cbool></Classical></DumpCall>"
 
-DSPLIT= "<DumpSplit>whatever</DumpSplit>"
+DSPLIT= "<DumpSplit>whatever</DumpSplit>"
+
+DUMPSINGLECALL = "<Dump>" +DCALL+"</Dump>"
+
+DUMPTWOCALL = "<Dump>" +DCALL+DCALL2+"</Dump>"
+DUMPCALLANDSPLIT = "<Dump>" +DCALL+DSPLIT+"</Dump>"
+DUMPCALLSPLITCALL = "<Dump>" +DCALL+DSPLIT+DCALL2+"</Dump>"
+DUMPSPLIT = "<Dump>" +DSPLIT+"</Dump>"

GUI/spec/specdata/quantum_stack_data.rb

   "<Qubits><pair><qz/><qz/></pair></Qubits></Qstack>"
 QSVAL5 = "<Qstack><int>-1</int><bool>True</bool><substacks></substacks><Value><number>0.5</number></Value></Qstack>"
 
+QSZ = "<Qstack><int>1</int><bool>True</bool><substacks></substacks><Zero/></Qstack>"
 QSQBHAD = make_multi_sstacks("<Qstack><int>1</int><bool>True</bool>",
   "<Qubits><pair><qz/><qz/></pair><pair><qz/><qo/></pair><pair><qo/><qz/></pair><pair><qo/><qo/></pair></Qubits></Qstack>",
   QSVAL5,4)
   "<Qubits><pair><qz/><qz/></pair><pair><qz/><qo/></pair><pair><qo/><qz/></pair><pair><qo/><qo/></pair></Qubits></Qstack></substacks>"+
   "<Qubits><pair><qz/><qz/></pair></Qubits></Qstack>"
 
-QB2WITHBOTTOM =  "<Qstack><int>2</int><bool>True</bool><substacks><bottom/></substacks><Qubits><pair><qz/><qz/></pair></Qubits></Qstack>"
+QB2WITHBOTTOM =  "<Qstack><int>2</int><bool>True</bool><substacks><bottom/></substacks><Qubits><pair><qz/><qz/></pair></Qubits></Qstack>"
+C1WITHBOTTOM =  "<Qstack><int>2</int><bool>True</bool><substacks><bottom/></substacks><Classical><cint>27</cint></Classical></Qstack>"
+AL1WITHBOTTOM =  "<Qstack><int>7</int><bool>False</bool><substacks><bottom/></substacks><AlgebraicData><string>Nil</string><StackAddresses></StackAddresses></AlgebraicData></Qstack>"
+
+BOTTOMS = [QB2WITHBOTTOM,C1WITHBOTTOM,AL1WITHBOTTOM]
+
+MIXED=[QSQBZero, QB2WITHBOTTOM,QSVAL5]
+
+ADDRESSES=[[1,QSQBZero],[-1,QSVAL5], [2,QB2WITHBOTTOM]]
+
+DIAGS=[[true,QSQBZero], [true,QSVAL5], [false,AL1WITHBOTTOM]]
+
+QS3LEVEL = make_multi_sstacks("<Qstack><int>3</int><bool>True</bool>",
+  "<Classical><cint>27</cint><cint>5</cint></Classical></Qstack>",
+  QSQBZero,3)

GUI/spec/utility/duck_matcher_spec.rb

+require 'spec/spec_helper'
+
+describe DuckMatcher do
+  it "is created from a start and stop string, followed by a third string" do
+    dm = DuckMatcher.new "start","stop", "entire"
+    dm.should_not be_nil
+  end
+  describe "match" do
+    before ("each") do
+      @dm = DuckMatcher.new "strt","stop", "entire"
+    end
+    it "matches for the third element first and returns that if it exists" do
+      m = @dm.match "entire"
+      m.length.should == 1
+      m[0].should == "entire"
+    end
+    it "returns nil if the input is empty" do
+      m = @dm.match ""
+      m.should be_nil
+    end
+    it "partitions the 'strtxxxstop' into a 1 element array ['strtxxxstop']" do
+      m = @dm.match "strtxxxstop"
+      m.length.should == 1
+      m[0].should == "strtxxxstop"
+    end
+    it "partitions the 'strtxxxstopstrtxxxstop' into a 1 element array ['strtxxxstop']" do
+      m = @dm.match "strtxxxstopstrtxxxstop"
+      m.length.should == 1
+      m[0].should == "strtxxxstop"
+    end
+    it "partitions the 'strtxxxstopstrtxxxstopstrtxxxstop' into a 1 element array ['strtxxxstop']" do
+      m = @dm.match "strtxxxstopstrtxxxstopstrtxxxstop"
+      m.length.should == 1
+      m[0].should == "strtxxxstop"
+    end
+    it "partitions the 'strtxxstrtxxxstopxstop' into a 1 element array ['strtxxstrtxxxstopxstop']" do
+      m = @dm.match "strtxxstrtxxxstopxstop"
+      m.length.should == 1
+      m[0].should == "strtxxstrtxxxstopxstop"
+    end
+    it "partitions the 'strtxxstrtxstrtxxstrtxxxstopxstopxxstopxstopstrtxxxstop' into a 1 element array ['strtxxstrtxstrtxxstrtxxxstopxstopxxstopxstop']" do
+      m = @dm.match "strtxxstrtxstrtxxstrtxxxstopxstopxxstopxstopstrtxxxstop"
+      m.length.should == 1
+      m[0].should == "strtxxstrtxstrtxxstrtxxxstopxstopxxstopxstop"
+    end
+  end
+end      

GUI/src/communications/compiler_server_connection.rb

   
   def get_qpo_program
     accum=""
-    lineno = 0
-    line='CS_T'
-    while line =~ /CS_/
-      line = @connection.readline #until line !~ /CS_/
-    end
+    #lineno = 0
+    line=bypass_cs_messages
     read_warning = (line =~ /w='YES'/)
-    #puts read_warning
-    @failed = false
-    @failure_message = ""
+    reset_failure_status
     while line and line != "</qpo>\n"  and line !~ /<\/compilefail/  and !@failed do
       #puts "lineno=#{lineno}; line='#{line}'"
-      @failed = true if line =~  /<compilefail/
-      read_failure_message if @failed
-      break if @failed
-      accum += line if line !~ /(CS_)|(<qpo)|(<compilefail)|(<getFirst)/
-      send_included_file(line) if line =~ /<getFirst>/
-      line = @connection.readline
-      lineno += 1
+      line = process_input_line line
+      # @failed = line =~  /<compilefail/
+      # read_failure_message if @failed
+      # break if @failed
+      # accum += line if line !~ command_start_regex
+      # send_included_file(line) if line =~ /<getFirst>/
+      # line = @connection.readline
+      #lineno += 1
     end
     read_failure_message if read_warning
     return accum
   end
+  
+  def process_input_line line
+    @failed = line =~  /<compilefail/
+    read_failure_message if @failed
+    return nil if @failed
+    accum += line if line !~ command_start_regex
+    send_included_file(line) if line =~ /<getFirst>/
+    @connection.readline
+  end
+  
+  def command_start_regex
+    /(CS_)|(<qpo)|(<compilefail)|(<getFirst)/
+  end
+  
+  def bypass_cs_messages
+    line='CS_T'
+    line = @connection.readline while line =~ /CS_/ #until line !~ /CS_/
+    line
+  end
+  
+  def reset_failure_status
+    @failed = false
+    @failure_message = ""
+  end
 
   def read_failure_message
     line = @connection.readline
     "Compile of #{file_name} was #{failed ? 'un' : ''}successful\n"+failure_message
   end
   
+  def base_file_from_line(line_input)
+    basef = line_input[/(<getFirst>)(.*)(<\/getFirst>)/,2]
+    File.exists?(basef) ? basef : @dir + "/" + basef
+  end
+  
   def send_included_file(line)
-    basef = line[/(<getFirst>)(.*)(<\/getFirst>)/,2]
-    f = File.exists?(basef) ? basef : @dir + "/" + basef
+    f = base_file_from_line line
     fdata=""
     if File.exists?(f)
       File.open(f) do |incfile|
         fdata = incfile.read
       end
-      @connection.puts "<file name='#{basef}'>"
-      @connection.puts fdata
-      @connection.puts "</file>"
+      write_specified_file f,fdata
     else
       @failed = true
       @failure_message =  "Unable to find or open file #{f}, Looking in #{Dir.pwd}"
     end
   end
+  
+  def write_specified_file(filename, filedata)
+    @connection.puts "<file name='#{File.basename filename}'>"
+    @connection.puts filedata
+    @connection.puts "</file>"
+  end
 
   def write_qpo_file
     connect if !connected?
-    @connection.puts "<sendversion />"
-    version = @connection.readline
-    version_line = "Compiler: Version="+CompilerServerConnection::makeVersionNumber(version)
-    File.open(File.dirname(@fname)+File::SEPARATOR+File.basename(@fname,".qpl")+".qpo","w+") do |f|
+    version_line = get_version_line
+    File.open(object_file_name,"w+") do |f|
       f.puts version_line
       f.puts @qpo_code
     end
   end
 
+  def object_file_name
+    File.dirname(@fname)+File::SEPARATOR+File.basename(@fname,".qpl")+".qpo"
+  end
+  
+  def get_version_line    
+    @connection.puts "<sendversion />"
+    version = @connection.readline
+    "Compiler: Version="+CompilerServerConnection::makeVersionNumber(version)
+  end
+  
   def self.makeVersionNumber(vstring)
     nums = vstring[/(\d+,)+\d+/].gsub(/,/,'.')
     return nums

GUI/src/communications/connection.rb

 
   def connect
     res = _make_connection
-
-    jar_path= File.expand_path(__FILE__)[Regexp.new /.*?jar!/]
-    if jar_path
-      jar_path=jar_path[5,jar_path.length - 18] #remove 'file:' from front, lqpl_gui.jar! from back
-    else
-      jar_path = File.expand_path(File.dirname(__FILE__))+"/../../"
-    end
+    jar_path = _set_up_jar_path
+    
     # puts " will try from #{jar_path}"
     if !res
       begin
         # try executing from PATH first - probably not right for testing.... 
         #TODO - add flag to pick order of these.
-        @process=ProcessBuilder.new(@connect_to, "").start
-        sleep 0.25
-        res2 = _make_connection
-        raise ServerProcessNotFound if !res2
+        _start_up_the_executable_in_a_process(@connect_to)
       rescue => e
         begin
           # Assume executables just below jar path 
           # Works for bundled executables.
-          @process=ProcessBuilder.new("#{jar_path}bin/#{@connect_to}", "").start
-          sleep 0.25
-          res2 = _make_connection
-          raise ServerProcessNotFound if !res2
+          _start_up_the_executable_in_a_process("#{jar_path}bin/#{@connect_to}")
         rescue => e1
           begin
             # assume one further .. and then over to out/bin 
             # works for rspec and cucumber 
-            @process=ProcessBuilder.new("#{jar_path}../out/bin/#{@connect_to}", "").start
-            sleep 0.25
-            res2 = _make_connection
-            raise ServerProcessNotFound if !res2
+            _start_up_the_executable_in_a_process("#{jar_path}../out/bin/#{@connect_to}")
           rescue => e2
             raise ServerProcessNotFound, "There was no process found on port #{@port}. Please start '#{@connect_to}'."
           end
       end
     end
   end
-
+  
+  def _set_up_jar_path
+    jar_path= File.expand_path(__FILE__)[Regexp.new /.*?jar!/]
+    if jar_path
+      jar_path=jar_path[5,jar_path.length - 18] #remove 'file:' from front, lqpl_gui.jar! from back
+    else
+      jar_path = File.expand_path(File.dirname(__FILE__))+"/../../"
+    end
+    jar_path
+  end
+  
+  def _start_up_the_executable_in_a_process(executable)
+    @process=ProcessBuilder.new(executable, "").start
+    sleep 0.25
+    res2 = _make_connection
+    raise ServerProcessNotFound if !res2
+  end
+  
   def _make_connection
 
     ["127.0.0.1", "::1", "localhost"].each do |addr|

GUI/src/lqpl/lqpl_menu.rb

   def initialize(parent)
     mbar = JMenuBar.new
 
+    menu_file = init_file_menu
+
+    menu_view =  init_view_menu
+
+    mbar.add(menu_file);
+    mbar.add(menu_view);
+
+    init_help_menu mbar
+
+    parent.set_menu_bar(mbar);
+    mbar.visible = true;
+  end
+  
+  def init_file_menu
     menu_file = JMenu.new("File")
     @file_load = JMenuItem.new("Load");
     @file_compile =  JMenuItem.new("Compile");
       @file_exit = JMenuItem.new("Exit")
       menu_file.add(@file_exit)
     end
+    menu_file
+  end
 
-    menu_view =  JMenu.new("View");
+  def init_view_menu
+    menu_view = JMenu.new("View");
     @view_classical_stack =  JMenuItem.new("Hide Classical Stack");
     @view_dump =  JMenuItem.new("Hide Dump");
     @view_executing_code =  JMenuItem.new("Hide Executing Code");
     menu_view.add(@view_dump);
     menu_view.add(@view_executing_code);
     menu_view.add(@view_stack_translation);
-
-    mbar.add(menu_file);
-    mbar.add(menu_view);
-
-
+    menu_view
+  end
+  
+  def init_help_menu mbar
     not_on_mac do
       menu_help = JMenu.new("Help")
       @help_about = JMenuItem.new("About")
       menu_help.add(@help_about)
       mbar.add(menu_help)
     end
-
-    parent.set_menu_bar(mbar);
-    mbar.visible = true;
   end
 
-
 end

GUI/src/lqpl/lqpl_model.rb

+JInteger = java_import java.lang.Integer
+
 class LqplModel < ApplicationModel
   attr_accessor :spinner_panel_visible, :button_panel_visible
   attr_accessor :step_spinner, :recursion_spinner, :recursion_multiplier_spinner, :tree_depth_spinner
   attr_accessor :frame_title
 
   def initialize
+    init_panels
+    init_spinners
+    init_buttons
+    init_view_menu
+    @frame_title = "Quantum Emulator"
+  end
+  
+  def init_panels
     @spinner_panel_visible = false
     @button_panel_visible = false
-    @step_spinner = java.lang.Integer.new(1)
-    @recursion_spinner = java.lang.Integer.new(1)
-    @recursion_multiplier_spinner = java.lang.Integer.new(10)
-    @tree_depth_spinner = java.lang.Integer.new(4)
+  end
+  
+  def init_spinners
+    @step_spinner = JInteger.new(1)
+    @recursion_spinner = JInteger.new(1)
+    @recursion_multiplier_spinner = JInteger.new(10)
+    @tree_depth_spinner = JInteger.new(4)
+  end
+  
+  def init_buttons
     @go_enabled = true
     @step_enabled = true
-
+  end
+    
+  def init_view_menu
     @view_menu_stack_translation_enabled = false
     @view_menu_dump_enabled = false
     @view_menu_executing_code_enabled = false
     @view_menu_executing_code_text = "Hide Executing Code"
     @view_menu_dump_text = "Hide Dump"
     @view_menu_classical_stack_text = "Hide Classical Stack"
-    @frame_title = "Quantum Emulator"
   end
 
   def toggle_view_menu(current_command)
   end
   
   def self.symbol_for_view_menu_item(current_command)
-    which_menu=current_command[1,current_command.size-1].collect(&:downcase).join("_")
+    which_menu=current_command[1,-1].collect(&:downcase).join("_")
     "view_menu_#{which_menu}_text=".to_sym
   end
 end

GUI/src/manifest.rb

 end
 
 
-%w{translate_line_ends xml_decode drawing}.each do |f|
+%w{translate_line_ends xml_decode drawing duck_matcher}.each do |f|
   require "utility/"+f
 end
 
 end
 
 
-%w{stack_translation code_pointer executable_code}.each do |rf|
+%w{stack_translation code_pointer executable_code dump_call dump_split dump quantum_stack}.each do |rf|
   require "panels/parsers/"+rf+"_parser"
 end
 

GUI/src/painting/canvas_size.rb

   end
   
   def self.new_from_subtree(subtree_array)
+    left = CanvasSize::subtree_left_width(subtree_array)
+    right = CanvasSize::subtree_right_width(subtree_array)
+    h = subtree_array.collect{|cs| cs.height_with_spacing}.max
+    self.new_with_measures(left,right,h)
+  end
+  
+  def self.subtree_left_width(subtree_array)
     mid = subtree_array.get_middle_element
     
-    left = CanvasSize::total_widths(subtree_array.get_left_partition)
-    left += mid.left_required_width if mid
-    
-    right = CanvasSize::total_widths(subtree_array.get_right_partition)
-    right += mid.right_required_width if mid
+    CanvasSize::total_widths(subtree_array.get_left_partition)+(mid ? mid.left_required_width : 0)
+  end
+  
+  def self.subtree_right_width(subtree_array)
+    mid = subtree_array.get_middle_element
     
-    h = subtree_array.collect{|cs| cs.height_with_spacing}.max
-    self.new_with_measures(left,right,h)
+    CanvasSize::total_widths(subtree_array.get_right_partition)+(mid ? mid.right_required_width : 0)
   end
   
   def self.total_widths(sizes)
   # handle having a midpoint = equals size 0
   def self.compute_offsets(sizes)
     return [] if !sizes or sizes.length == 0
+      
     mid = sizes.get_middle_element
+    CanvasSize::left_offsets(sizes,mid) + CanvasSize::right_offsets(sizes,mid)
+  end
+  
+  def self.left_offsets(sizes,mid)  
     lefts = sizes.get_left_partition.tails.collect {|la| -CanvasSize.width_to_right_of_head(la)}
     lefts.collect! {|b| b-mid.left_required_width} if mid
     lefts << 0 if mid
+    lefts
+  end
+  
+  def self.right_offsets(sizes,mid)
     rights = sizes.get_right_partition.heads.collect{|ra| CanvasSize.width_to_left_of_tail(ra)}
     rights.collect!{|r| r+mid.right_required_width} if mid
-    lefts + rights
   end
 
   def initialize_with_measures(left,right,height)

GUI/src/panels/dump/dump_call_model.rb

-class DumpCallModel
+class DumpCallModel < ApplicationModel
 
   def initialize(inx)
     self.dumpcall=inx
   end
 
   def dumpcall=(in_xml)
-    m = DC_PATTERN.match in_xml
-    raise ModelCreateError, "Invalid dump_call: #{in_xml}" if !m
-    @ret_offset=m[1]
-    @ret_label=m[2]
+    dcp = DumpCallParser.new in_xml
+    @ret_offset=dcp.parsed_value[0]
+    @ret_label=dcp.parsed_value[1]
     @cstack = ClassicalStackModel.new
-    @cstack.classical_stack= m[3]
+    @cstack.classical_stack= dcp.parsed_value[2]
   end
 
   def text
     "Return to #{@ret_label}(#{@ret_offset}). CS=#{@cstack.to_a}"
   end
 
-  DC_PATTERN= Regexp.new /<DumpCall><int>(\d*)<\/int><string>([\w\d_]*)<\/string>(<Classical>.*?<\/Classical>)<\/DumpCall>/
 end

GUI/src/panels/dump/dump_model.rb

 require "panels/dump/dump_call_model"
 require "panels/dump/dump_split_model"
 
-class DumpModel <XmlBasedModel
+class DumpModel <ApplicationModel
 
   attr_accessor :dump
   
   def dump=(in_xml)
-    @dump = check_and_return_value(DUMP_PATTERN,in_xml,
-    lambda { |m| DumpModel::dump_values_to_list m})
+    dp = DumpParser.new in_xml
+    @dump = dp.parsed_value
   end
 
   def text=(whatev)
     "<html><ol>"+inside+"</ol></html>"
   end
 
-  def self.dump_values_to_list(dumpvals)
-    values_to_list dumpvals, DUMP_LIST_PATTERN  do |ret, dv|
-      ret << DumpCallModel.new(dv[1]) if dv[1]
-      ret << DumpSplitModel.new(dv[2]) if dv[2]
-    end
-  end
-  DUMP_LIST_PATTERN = Regexp.new /(<DumpCall>.*?<\/DumpCall>)|(<DumpSplit>.*?<\/DumpSplit>)/
-  DUMP_PATTERN= Regexp.new /<Dump>(.*?)<\/Dump>/
+
 end

GUI/src/panels/dump/dump_split_model.rb

-class DumpSplitModel <XmlBasedModel
+class DumpSplitModel <ApplicationModel
 
   def initialize(inx)
     self.dumpsplit=inx
   end
 
   def dumpsplit=(in_xml)
-    m = DS_PATTERN.match in_xml
-    raise ModelCreateError, "Invalid dump split: #{in_xml}" if !m
-    @ds_text= m[0]
+    dsp = DumpSplitParser.new in_xml
+    @ds_text= dsp.parsed_value
   end
 
   def text
     @ds_text
   end
-
-  DS_PATTERN= Regexp.new /<DumpSplit>(.*?)<\/DumpSplit>/
 end

GUI/src/panels/executable_code/code_pointer.rb

-class CodePointer
+class CodePointer < ApplicationModel
   attr_accessor :qpo_method
   attr_accessor :line_number
   def initialize(xml_string)

GUI/src/panels/executable_code/executable_code_model.rb

 require 'panels/executable_code/code_pointer'
 
-class ExecutableCodeModel
+class ExecutableCodeModel < ApplicationModel
   attr_accessor :the_code
   attr_accessor :the_code_pointer
   attr_accessor :the_code_was_updated

GUI/src/panels/executable_code/executable_code_view.rb

   end
 
   def create_tabbed_views(code_map)
-    code_tab_pane = codeTabbedPane
-    codeTabbedPane.remove_all
-    @qpo_method_to_tab_map = {}
-    @qpo_method_and_line_to_selection_start_and_end_map = {}
+    code_tab_pane = reset_tabbed_panes_and_maps
     i = 0
     code_map.each do |qpo_method, qpo_ins|
-      instructions_text_area = JTextArea.new(qpo_ins.join("\n"), qpo_ins.length, WIDTH_OF_TEXT_PANE)
-      instructions_text_area.editable = false
-      instructions_text_area.selection_start = 0
-      instructions_text_area.selection_end = 0
-      scroll_pane = JScrollPane.new(instructions_text_area)
-      code_tab_pane.add_tab(qpo_method.to_s, scroll_pane)
+      code_tab_pane.add_tab(qpo_method.to_s, ExecutableCodeView::init_scroll_pane(qpo_ins))
       @qpo_method_to_tab_map[qpo_method] = i
       text_len=0
       qpo_ins.each_with_index do |ins_line, ind|
-        @qpo_method_and_line_to_selection_start_and_end_map[ExecutableCodeView::make_selection_key(qpo_method,ind)] = [text_len, text_len+1+ins_line.length]
+        add_to_selection_start_and_end_map(qpo_method, ins_line, ind, text_len)
         text_len += 1+ins_line.length
       end
       i += 1
     end
   end
-
+  
+  def reset_tabbed_panes_and_maps
+    code_tab_pane = codeTabbedPane
+    codeTabbedPane.remove_all
+    @qpo_method_to_tab_map = {}
+    @qpo_method_and_line_to_selection_start_and_end_map = {}
+  end
+  
+  def add_to_selection_start_and_end_map(qpo_method,ins_line,index,text_len)
+    @qpo_method_and_line_to_selection_start_and_end_map[ExecutableCodeView::make_selection_key(qpo_method,index)] = [text_len, text_len+1+ins_line.length]    
+  end
+  
+  def self.init_scroll_pane qpo_ins
+    JScrollPane.new(ExecutableCodeView::init_instructions_text_area qpo_ins)
+  end
+  
+  def self.init_instructions_text_area qpo_ins
+    instructions_text_area = JTextArea.new(qpo_ins.join("\n"), qpo_ins.length, WIDTH_OF_TEXT_PANE)
+    instructions_text_area.editable = false
+    instructions_text_area.selection_start = 0
+    instructions_text_area.selection_end = 0
+  end
+  
   #todo - revise this and code_pointer to know when just the line changes, rather than the whole thing.
   def set_highlight_for_code_pointer(code_pointer)
     return if !@qpo_method_to_tab_map[code_pointer.qpo_method]
     selection_key = ExecutableCodeView::mangle_code_pointer_to_selection_key(code_pointer)
     return if !@qpo_method_and_line_to_selection_start_and_end_map[selection_key]
     selection_bounds = @qpo_method_and_line_to_selection_start_and_end_map[selection_key]
+    set_selection_bounds_in_view(codeTabbedPane, selection_bounds)
+  end
+  
+  def set_selection_bounds_in_view(codeTabbedPane,selection_bounds)
     jt = codeTabbedPane.selected_component.viewport.view
     jt.request_focus(true) # deprecated method, but otherwise the highlight does not show when switching qpo_methods
     jt.selection_start = 0  # reset to handle "use" case where we go back (loop) in the code

GUI/src/panels/parsers/abstract_pattern_parser.rb

 end
 
 class AbstractPatternParser
+  attr_reader :md
+  
   def initialize(in_string)
     @md = self.class.top_level_regexp.match in_string
     raise ParserError, "No match -#{self.class.top_level_regexp}- to -#{in_string}-" unless @md
   end
   
   def self.top_level_regexp
+    self.surround_with_start_end self.embeddable_top_level_regexp
+  end
+  
+  
+  def self.embeddable_top_level_regexp
     Regexp.new /^$/
   end
   
+  def self.surround_with_start_end(regexp)
+    Regexp.new "^"+regexp.source+"$"
+  end
 end

GUI/src/panels/parsers/classical_pattern_parser.rb

 class ClassicalPatternParser < AbstractListPatternParser
   
-  def self.top_level_regexp
-    Regexp.new /^<Classical>(?<classical_values>((<cint>(-?\d+)<\/cint>)|(<cbool>(True|False)<\/cbool>))*)<\/Classical>$/
+  def self.embeddable_top_level_regexp
+    Regexp.new "<Classical>(?<classical_values>((<cint>(-?\\d+)</cint>)|(<cbool>(True|False)</cbool>))*)</Classical>"
   end
   
   LIST_PATTERN = Regexp.new /^(<cint>(?<int_value>-?\d+)<\/cint>)|(<cbool>(?<bool_value>True|False)<\/cbool>)/

GUI/src/panels/parsers/code_pointer_parser.rb

 class CodePointerParser < AbstractPatternParser
   
-  def self.top_level_regexp
-    Regexp.new /^<pair><string>(?<key>.*?)<\/string><int>(?<value>\d*)<\/int><\/pair>$/
+  def self.embeddable_top_level_regexp
+    Regexp.new "<pair><string>(?<key>.*?)</string><int>(?<value>\\d*)</int></pair>"
   end
   
   def parsed_value

GUI/src/panels/parsers/data_pattern_parser.rb

   LIST_PATTERN = Regexp.new /^(<int>(?<address>\d*)<\/int>)/
 
 
-  def self.top_level_regexp
-    Regexp.new /^<AlgebraicData>(?<constructors>(<string>([\w\d_]*)<\/string><StackAddresses>((<int>(\d*)<\/int>)*)<\/StackAddresses>)+)<\/AlgebraicData>$/
+  def self.embeddable_top_level_regexp
+    Regexp.new "<AlgebraicData>(?<constructors>(<string>([\\w\\d_]*)<\/string><StackAddresses>"+
+        "((<int>(\\d*)</int>)*)</StackAddresses>)+)</AlgebraicData>"
   end
 
   def parse_list

GUI/src/panels/parsers/dump_call_parser.rb

+class DumpCallParser < AbstractPatternParser
+  
+  def self.embeddable_top_level_regexp
+    Regexp.new "<DumpCall><int>(?<return_offset>\\d*)</int><string>(?<return_label>[\\w\\d_]*)</string>(?<classical_stack>" +
+      ClassicalPatternParser.embeddable_top_level_regexp.to_s+")</DumpCall>"
+  end
+  
+  def parsed_value
+    [@md[:return_offset],@md[:return_label], @md[:classical_stack]]
+  end
+  
+end

GUI/src/panels/parsers/dump_parser.rb

+class DumpParser < AbstractListPatternParser
+  def self.embeddable_top_level_regexp
+    Regexp.new "<Dump>(?<dump_list>("+DUMP_LIST_PATTERN.source+")*)</Dump>"
+  end
+  
+  def parse_list
+    DumpParser::values_to_list @md[:dump_list], DUMP_LIST_PATTERN  do |ret, dv|
+      ret << DumpCallModel.new(dv[:dump_call]) if dv[:dump_call]
+      ret << DumpSplitModel.new(dv[:dump_split]) if dv[:dump_split]
+    end
+  end
+  
+  DUMP_LIST_PATTERN = Regexp.new "(?<dump_call>"+DumpCallParser.embeddable_top_level_regexp.source+
+      ")|(?<dump_split>"+DumpSplitParser.embeddable_top_level_regexp.source+")"
+  
+end

GUI/src/panels/parsers/dump_split_parser.rb

+class DumpSplitParser < AbstractPatternParser
+  
+  def self.embeddable_top_level_regexp
+    Regexp.new "<DumpSplit>(?<dumpsplit>.*)</DumpSplit>"
+  end
+  
+  def parsed_value
+    @md[:dumpsplit]
+  end
+end

GUI/src/panels/parsers/executable_code_parser.rb

 class ExecutableCodeParser < AbstractListPatternParser
   
-  def self.top_level_regexp
-    Regexp.new /^<Code><map>(?<code_map>(<kvpair><key><string>(.*?)<\/string><\/key><value><instructions>(<i>(.*?)<\/i>)*?<\/instructions><\/value><\/kvpair>)*?)<\/map><\/Code>$/
+  def self.embeddable_top_level_regexp
+    Regexp.new "<Code><map>(?<code_map>("+
+       KVPAIRS_PATTERN.source+")*?)</map></Code>"
   end
   
   def parse_list
       retmap[kvpair[:code_key].to_sym] = ExecutableCodeParser::instructions_to_list kvpair[:instructions_list]
     end
   end
-    # 
-    # def self.kv_pairs_to_map(kvps)
-    #   return {} if !kvps or kvps == ""
-    #   ret = {}
-    #   kvp = KVPAIRS_PATTERN.match kvps
-    #   return ret if !kvp
-    #   ret[kvp[1].to_sym] = ExecutableCodeModel::instructions_to_list(kvp[2])
-    #   matched_len = kvp[0].length
-    #   while kvp
-    #     kvp = KVPAIRS_PATTERN.match(kvps[matched_len,kvps.length])
-    #     return ret if !kvp
-    #     ret[kvp[1].to_sym] = ExecutableCodeModel::instructions_to_list(kvp[2])
-    #     matched_len += kvp[0].length
-    #   end
-    # end
+  
 
   def self.instructions_to_list(instructions)
     count = 0
   end
 
 
-  INSTRUCTIONS_PATTERN = Regexp.new /<i>(.*?)<\/i>/
+  INSTRUCTIONS_PATTERN = Regexp.new "<i>(.*?)</i>"
 
-  KVPAIRS_PATTERN = Regexp.new   /^<kvpair><key><string>(?<code_key>.*?)<\/string><\/key><value><instructions>(?<instructions_list>(<i>(.*?)<\/i>)*?)<\/instructions><\/value><\/kvpair>/
+  KVPAIRS_PATTERN = Regexp.new "<kvpair><key><string>(?<code_key>.*?)</string></key><value>"+
+    "<instructions>(?<instructions_list>("+INSTRUCTIONS_PATTERN.source+
+    ")*?)</instructions></value></kvpair>"
 
 end

GUI/src/panels/parsers/quantum_stack_parser.rb

+class QuantumStackParser < AbstractListPatternParser
+
+  def self.embeddable_top_level_regexp
+    Regexp.new "<bottom/>|"+"<Qstack><int>(?<stackaddress>-?(\\d)*)<\/int>"+
+      "<bool>(?<on_diagonal>(True)|(False))</bool>"+
+      "<substacks>(?<substacks>.*)</substacks>"+
+      "(?<descriptor>(<Zero/>)|(<Value>.*</Value>)|(<Qubits>.*</Qubits>)|"+
+      "(<Classical>.*</Classical>)|(<AlgebraicData>.*</AlgebraicData>))"+
+      "</Qstack>"
+  end
+    
+  def self.initial_qstack_regexp
+    Regexp.new "^"+QuantumStackParser::embeddable_top_level_regexp.source
+  end
+  
+  def self.sub_qstack_matcher
+    DuckMatcher.new "<Qstack>", "</Qstack>", "<bottom/>"
+  end
+  
+  def initialize(in_qst)
+    if in_qst.respond_to? :substacks_string
+      @md = in_qst.md
+      @parsed_list = in_qst.substacks
+    else
+      super
+    end
+  end
+  
+  def stackaddress
+    @md[:stackaddress].to_i
+  end
+  
+  def descriptor
+    @md[:descriptor]
+  end
+  
+  def on_diagonal?
+    @md[:on_diagonal] == "True"
+  end
+  
+  def substacks_string
+    @md[:substacks]
+  end
+  
+  def bottom?
+    @md[0] == "<bottom/>"
+  end
+  
+  def substacks
+    @parsed_list
+  end
+
+  def parse_list
+    return [] if !substacks_string || substacks_string == ""
+    QuantumStackParser::values_to_list substacks_string, QuantumStackParser::sub_qstack_matcher do |retval, qmd|
+      retval << QuantumStackParser.new(qmd[0])
+    end
+  end
+  
+end

GUI/src/panels/parsers/qubit_pattern_parser.rb

 class QubitPatternParser < AbstractListPatternParser
   
-  LIST_PATTERN = Regexp.new /^(<pair>(?<first_qubit>(<qz\/>)|(<qo\/>))(?<second_qubit>(<qz\/>)|(<qo\/>))<\/pair>)/
+  LIST_PATTERN = Regexp.new "<pair>(?<first_qubit>(<qz/>)|(<qo/>))(?<second_qubit>(<qz/>)|(<qo/>))</pair>"
   # match 2 and 5
   
-  def self.top_level_regexp
-    Regexp.new /^<Qubits>(?<qubits>(<pair>((<qz\/>)|(<qo\/>))((<qz\/>)|(<qo\/>))<\/pair>){1,4})<\/Qubits>$/
+  def self.embeddable_top_level_regexp
+    Regexp.new "<Qubits>(?<qubits>("+
+        LIST_PATTERN.source+"){1,4})<\/Qubits>"
   end
     
   

GUI/src/panels/parsers/stack_translation_parser.rb

 class StackTranslationParser < AbstractListPatternParser
   
-  def self.top_level_regexp
-    Regexp.new /^<MMap>(?<maps>(<map>(<kvpair><key><string>(.*?)<\/string><\/key><value><int>(\d*)<\/int><\/value><\/kvpair>)*<\/map>)*)<\/MMap>$/
+  def self.embeddable_top_level_regexp
+    Regexp.new "<MMap>(?<maps>("+LIST_PATTERN.source+")*)</MMap>"
   end
   
   def parse_list
     end
   end
   
+  KVPATTERN = Regexp.new "<kvpair><key><string>(?<key>.*?)</string></key><value><int>(?<value>\\d*)</int></value></kvpair>"
 
-  LIST_PATTERN = Regexp.new /^<map>(?<key_value_pairs>(<kvpair><key><string>(.*?)<\/string><\/key><value><int>(\d*)<\/int><\/value><\/kvpair>)*)<\/map>/
-  KVPATTERN = Regexp.new /^<kvpair><key><string>(?<key>.*?)<\/string><\/key><value><int>(?<value>\d*)<\/int><\/value><\/kvpair>/
+  LIST_PATTERN = Regexp.new "<map>(?<key_value_pairs>("+KVPATTERN.source+")*)</map>"
 
 end

GUI/src/panels/parsers/value_pattern_parser.rb

 class ValuePatternParser < AbstractPatternParser
   
-  def self.top_level_regexp
-    Regexp.new /^<Value>(<number>)?(1|1\.|1\.0|0?\.\d*|\d\.\d*e-\d\d?)(<\/number>)?<\/Value>$/
+  def self.embeddable_top_level_regexp
+    Regexp.new "<Value>(<number>)?(1|1\\.|1\\.0|0?\\.\\d*|\\d\\.\\d*e-\\d\\d?)(</number>)?</Value>"
   end
   
   def parsed_value

GUI/src/panels/parsers/zero_pattern_parser.rb

 class ZeroPatternParser < AbstractPatternParser
   
-  def self.top_level_regexp
-    Regexp.new /^<Zero\/>$/
+  def self.embeddable_top_level_regexp
+    Regexp.new "<Zero/>"
   end
   
   def parsed_value

GUI/src/panels/quantum_stack/descriptor/abstract_descriptor_painter.rb

 
   def paintModelAtPoint(g,center)
     draw_colour_filled_shape(g,my_shape(center), my_colour)
-    draw_text_to_left_of_point(g,"#{@model_element.name}",Point.new(center.x-node_size, center.y)) if @model_element.name
-    draw_text_centered_at_point(g,"#{@model_element.value}",Point.new(center.x, center.y+node_size)) if @model_element.length == 0
+    paint_name(g,center) if @model_element.name
+    paint_value(g,center) if @model_element.length == 0
   end
 
+  def paint_name(g,center)
+    draw_text_to_left_of_point(g,"#{@model_element.name}",Point.new(center.x-node_size, center.y))
+  end
+  
+  def paint_value(g,center)
+    draw_text_centered_at_point(g,"#{@model_element.value}",Point.new(center.x, center.y+node_size)) 
+  end
+  
   alias :paint_model_at_point :paintModelAtPoint
   # end of painter interface
 
   def model_paint_size(g)
 
-    left_width = half_node_size
-    left_width += get_string_size(g,"#{@model_element.name}").width + node_size if @model_element.name
-    right_width = half_node_size
-
     height  =  node_size
-    valsize =  get_string_size(g," #{@model_element.value} ")
-    height  += valsize.height + half_node_size if @model_element.length == 0
-    right_width   =  [right_width,valsize.width*0.5].max
-    left_width = [left_width,valsize.width*0.5].max
+    valsize =  get_value_canvas_size g
+    height  += valsize.height_with_spacing if @model_element.length == 0
+    
+    right_width   =  valsize.right_required_width
+    left_width    =  [half_node_size + name_width(g),valsize.left_required_width].max
+    
     CanvasSize.new_with_measures(left_width, right_width, height)
   end
 
+  def get_value_canvas_size(g)
+    valsize = get_string_size(g," #{@model_element.value} ")
+    CanvasSize.new(valsize.width*0.5,valsize.width*0.5,valsize.height)
+  end
+  
+  def name_width g
+    return get_string_size(g,"#{@model_element.name}").width + node_size if @model_element.name
+    0
+  end
 
 
 end

GUI/src/panels/quantum_stack/quantum_stack_model.rb

-class QuantumStackModel < XmlBasedModel
+class QuantumStackModel < ApplicationModel
 
   attr_accessor :substacks
   attr_accessor :descriptor
     raise ModelCreateError, "QuantumStack: Missing Stack Translation" if @stack_translation.nil?
     return if !in_qstack
     @preferred_size = nil
-    @bottom = in_qstack == "<bottom/>"
-    if !bottom?
-      decode_stack_data_from_xml in_qstack
-
-      @descriptor.name = make_name(:use_stack_address)
-    else
-      @substacks = []
-    end
+    decode_stack_data_from_xml in_qstack
   end
   
   def decode_stack_data_from_xml(in_qstack)
-    matched = SingleQSMatcher.new  in_qstack
-    @stackaddress = matched.stackaddress
-    @on_diagonal = matched.on_diagonal?
-    @substacks = QuantumStackModel::make_multiple_stacks(matched.substacks, @stack_translation)
-    @descriptor = AbstractDescriptorModel.make_instance matched.descriptor
+    qpp = QuantumStackParser.new  in_qstack
+    @bottom = qpp.bottom?
+    @substacks = []
+    return if bottom?
+      
+    @stackaddress = qpp.stackaddress
+    @on_diagonal = qpp.on_diagonal?
+    @substacks = qpp.substacks.collect do |ss| 
+      q = QuantumStackModel.new
+      q.stack_translation = @stack_translation
+      q.quantum_stack = ss
+      q
+    end  if qpp.substacks
+    set_descriptor qpp.descriptor
+  end
+  
+  def set_descriptor(xml_descriptor)
+    @descriptor = AbstractDescriptorModel.make_instance xml_descriptor
     @descriptor.class.validate_substacks_count(@substacks)
+    @descriptor.name = make_name(:use_stack_address)
   end
   
   def make_name(formatting)
     nm = (@stack_translation.reverse_lookup(@stackaddress)).to_s
-
-    case formatting
-    when :use_stack_address then
-      nm += "(#{@stackaddress})" if nm != "#{@stackaddress}"
-    end
+    nm += "(#{@stackaddress})" if nm != "#{@stackaddress}" && formatting == :use_stack_address
     nm = "" if nm == "-1"
     nm
   end
   end
 
 
-
-  def self.make_multiple_stacks(many_stacks, st)
-    return [] if many_stacks == ""
-    next_stack = QuantumStackModel::get_next_qstack(many_stacks)
-    raise InvalidInput, many_stacks if !next_stack
-    rval = []
-    q = QuantumStackModel.new
-    q.stack_translation = st
-    q.quantum_stack = next_stack[0]
-    rval << q
-    while next_stack
-      next_stack = QuantumStackModel::get_next_qstack(next_stack[1])
-      return rval if !next_stack
-      q = QuantumStackModel.new
-      q.stack_translation = st
-      q.quantum_stack = next_stack[0]
-      rval << q
-    end
-    rval
-  end
-
-  def self.get_next_qstack(multi_stacks)
-    return nil if !multi_stacks or multi_stacks == ""
-    if multi_stacks =~ /^<bottom\/>/
-      len = 9
-    else
-      len = QuantumStackModel::find_end_index_for_start_in_data(multi_stacks,"<Qstack>","</Qstack>")
-    end
-    
-    # len = 8 # length of "<Qstack>"
-    # in_count = 1
-    # while in_count > 0
-    #   len += 1
-    #   in_count += 1 if multi_stacks[len,8] == "<Qstack>"
-    #   in_count -= 1 if multi_stacks[len,9] == "</Qstack>"
-    # end
-    # len += 9
-    return [multi_stacks[0,len], multi_stacks[len, multi_stacks.length - len + 1]]
-  end
-
-  def self.find_end_index_for_start_in_data(data,start_string,end_string)
-    len=start_len = start_string.size
-    end_len = end_string.size
-    in_count = 1
-    while in_count > 0
-      len +=1
-      in_count += 1 if data[len,start_len] == start_string
-      in_count -= 1 if data[len,end_len] == end_string
-    end
-    len+ end_len
-  end
-
-  class SingleQSMatcher
-    def initialize(in_data)
-      @md = SINGLE_QS_PATTERN.match in_data
-      raise ModelCreateError, in_data if !@md
-    end
-    
-    def stackaddress
-      @md[:stackaddress].to_i
-    end
-    
-    def descriptor
-      @md[:descriptor]
-    end
-    
-    def on_diagonal?
-      @md[:on_diagonal] == "True"
-    end
-    
-    def substacks
-      @md[:substacks]
-    end
-  end
-  
-  MMAP_PATTERN = Regexp.new /^<MMap>(.*)<\/MMap>$/
-  LIST_ELEMENT_PATTERN = Regexp.new /^<map>(.*?)<\/map>/
-  KVPATTERN = Regexp.new /^<kvpair><key><string>(.*?)<\/string><\/key><value><int>(\d*)<\/int><\/value><\/kvpair>/
-
-
-  SINGLE_QS_PATTERN = Regexp.new /^<Qstack>
-      <int>(?<stackaddress>-?(\d)*)<\/int>  #Stackaddress ([1])
-      <bool>(?<on_diagonal>(True)|(False))<\/bool> #on diagonal ([3])
-      <substacks>(?<substacks>.*)<\/substacks> # the substacks ([6])
-      (?<descriptor>(<Zero\/>)|(<Value>.*<\/Value>)|(<Qubits>.*<\/Qubits>)|(<Classical>.*<\/Classical>)|(<AlgebraicData>.*<\/AlgebraicData>))  # stack descriptor [7]
-      <\/Qstack>/x
-
-
 end

GUI/src/panels/stack_translation/stack_translation_model.rb

-class StackTranslationModel < XmlBasedModel
+class StackTranslationModel < ApplicationModel
   attr_accessor :stack_translation
   attr_accessor :text
 

GUI/src/utility/duck_matcher.rb

+class DuckMatcher
+  def initialize(start,stop, entire_string)
+    @matchss = Regexp.new "(?<strt>"+start+")|(?<stop>"+stop+")|(?<all_of_it>"+entire_string+")"
+  end
+  
+  def match(input)
+    @recurss = 0
+    current_position = 0
+    md = @matchss.match input
+    return [md[0]] if md[:all_of_it]
+    while md do
+      return [input[0,current_position+md.end(0)]] if _matched_paired_start_stop?(md)
+      current_position += md.end(0)
+      md = @matchss.match input[current_position, -1]
+    end
+    return nil
+  end  
+  
+  def _matched_paired_start_stop? md
+    @recurss +=1 if md[:strt]
+    @recurss -=1 if md[:stop]
+    @recurss == 0
+  end
+end

GUI/src/utility/monkey/array.rb

   
   private
   def _get_middle_element_as_array
-    self[self.size/2,-((-self.size/2).ceil+(self.size/2.floor))]
+    half_size = self.size/2
+    self[half_size,-((-half_size).ceil+(half_size.floor))]
   end
   
 end

GUI/src/xml_based_model.rb

-class XmlBasedModel <ApplicationModel
-  include XmlDecode
-  attr_accessor :value
-  attr_accessor :name
-
-
-  def check_and_return_value(pattern,in_string,data_parser)
-    matched = pattern.match in_string
-    raise ModelCreateError, "Invalid input for #{self.class}: #{in_string}" if ! matched
-    data_parser.call matched[1]
-  end
-
-end