Author Topic: How to test a class / method with OxygenBasic?  (Read 2691 times)

0 Members and 1 Guest are viewing this topic.

Arnold

  • Guest
How to test a class / method with OxygenBasic?
« on: February 24, 2015, 11:11:56 AM »
Hi Charles,

may I ask your advice? In my simple manner of programming I use print and waitkey statements to set some breakpoints, but I do not know how this works efficiently in debugging a class / method. OOP is a mystery for me.

For instance I indented indenter.o2bas with itself. My Editor recognizes out.bas as a binary file and opens it in HEX mode. Using Scite I can see NUL characters in out.bas prior to every do loop. But I do not really know where to look for. Line 38 (bb=b) makes no sense, but changing to b=bb results in an endless loop. I look in the code at the locations with '0' and 'do' and feel a bit helpless. Is there a systematic way how I could test / debug a method / class in OxygenBasic?

Roland

Charles Pegge

  • Guest
Re: How to test a class / method with OxygenBasic?
« Reply #1 on: February 24, 2015, 01:10:54 PM »
Hi Roland,

For debugging classes, you treat methods exactly like a function or sub. Normally, I use print statements, or printl for console output.

But I am about to adapt this code for use as an Oxide utility. It is very old and needs a thorough rework, as well as a simple text interface instead of loading/saving files.

.....

This will also clean out any right-hand space, and replace nulls etc with spaces.

tools/codeman/indenter.o2bas
SEE UPDATE IN LATER POSTING

Code: OxygenBasic
  1.  
« Last Edit: February 25, 2015, 12:00:00 PM by Charles Pegge »

Aurel

  • Guest
Re: How to test a class / method with OxygenBasic?
« Reply #2 on: February 24, 2015, 03:11:45 PM »
well ..this looks interesting :D

Arnold

  • Guest
Re: How to test a class / method with OxygenBasic?
« Reply #3 on: February 25, 2015, 12:34:16 AM »
Hi Charles,

the analogy: method and function / sub is very helpful for me. Thinking about this I can see class like a user defined type which contains some data as members and some procedures which can deal with this data.  Comparing the code above with the previous indenter.o2bas I can see that there are variables which are valid throuhout the program, vars which are valid in a class and vars which are valid in a method. And using print as breakpoints in a method should work as usual. Looking in Wikipedia ... ok, there are some more things which I have to learn about. But I have not come so far until now. I am only accustomed to a structure with procedures and then a main loop.

Using the code above still does not work. (But it looks much more understandable to me now). If I create a copy of the code as in.txt, Scite shows the NUL characters in out.bas and oxide.exe loads the file until the first do.

Please give me a chance. I would like to find out this afternoon what happens.

Roland

Charles Pegge

  • Guest
Re: How to test a class / method with OxygenBasic?
« Reply #4 on: February 25, 2015, 02:53:06 AM »
Hi Roland,

Yes, a Class is a fusion of type and functions. A function belonging to the class is called a method, and all member variables of the class are visible to the methods.

Internally, Oxygen's native objects look exactly like variables defined by traditional Basic UDTs

Indenter works with the test source code (based on one of Peter's old programs) but has not been tested on much else. So I am about to hook it up to Oxide for a full workout.

Charles Pegge

  • Guest
Re: How to test a class / method with OxygenBasic?
« Reply #5 on: February 25, 2015, 12:05:15 PM »
Fixed bug causing space(n) to deliver wide characters (0x0020)

Oxygen DLL Update (200k)
http://www.oxygenbasic.org/o2zips/Oxygen.zip

OxyMin Update (800k)
http://www.oxygenbasic.org/o2zips/OxyMin.zip

OxygenBasic Full Update (4700k)
http://www.oxygenbasic.org/o2zips/OxygenBasic.zip

Another Test Piece:
ind1.o2bas
Code: OxygenBasic
  1. sys a,b
  2. if a then
  3. if b
  4. do
  5. a=b
  6. b=a
  7. do
  8. exit do
  9. continue do
  10. end do
  11. exit do
  12. continue do
  13. while a>b
  14. exit while
  15. wend
  16. select a
  17. case 1
  18. b=1
  19. case 2
  20. b=2
  21. end select
  22. for a=1 to 2
  23. exit for
  24. next
  25. end do
  26. end if
  27. end if
  28.  
Result:
Code: OxygenBasic
  1.   sys a,b
  2.   if a then
  3.      if b
  4.         do
  5.            a=b
  6.            b=a
  7.            do
  8.               exit do
  9.               continue do
  10.            end do
  11.            exit do
  12.            continue do
  13.            while a>b
  14.               exit while
  15.            wend
  16.            select a
  17.            case 1
  18.               b=1
  19.            case 2
  20.               b=2
  21.            end select
  22.            for a=1 to 2
  23.               exit for
  24.            next
  25.         end do
  26.      end if
  27.   end if
  28.  


Indenter.o2bas Updated
Code: OxygenBasic
  1.  
  2.   'FORMATTING SOURCE CODE
  3.  '======================
  4.  
  5.  
  6.  
  7.    =============
  8.    class wordman
  9.    =============
  10.  
  11.   sys    bb   'starting position
  12.  sys    bc   'starting position of word
  13.  sys    aa   'ascii code of word
  14.  sys    le   'length of word
  15.  string w    'temp word
  16.  
  17.   method skiplspace(s as string, i as sys)
  18.   ========================================
  19.   sys a
  20.   if i>len(s) then exit sub
  21.   do
  22.     a=asc s,i
  23.     select a
  24.     case 0         : exit do
  25.     case 13        : exit do 'exit at end of a line
  26.    case 10        : exit do
  27.     case 33 to 255 : exit do 'exit at start of word
  28.    end select
  29.     i++
  30.   end do
  31.   end method
  32.  
  33.   method getword(string s, sys*b) as string
  34.   =========================================
  35.   sys a,c,d
  36.   a=0
  37.   bb=b
  38.   do
  39.     c=asc s,b
  40.     select c
  41.     case 0, 33 to 255 : exit do
  42.     end select
  43.     b++
  44.   end do
  45.   bc=b
  46.   aa=c
  47.   select c
  48.   case 34,96 'CAPTURE QUOTES
  49.    do
  50.       b++
  51.       d=asc s,b
  52.       if d=0 or d=c then b+=1 : jmp fwd done
  53.     end do
  54.   end select
  55.   do
  56.     c=asc s,b
  57.     select c
  58.     case 0 to 32    : exit do 'white space
  59.    case 35,95      :         ' # _
  60.     case 48 to 57   :         'numbers
  61.    case 65 to 90   :         'capitals
  62.    case 97 to 122  :         'lower case
  63.    case 127 to 255 :         'higher ascii
  64.    case else
  65.       if b=bc then b+=1       ' self-terminating symbol
  66.      exit do
  67.     end select
  68.     b++
  69.   end do
  70.   '
  71.  done:
  72.   '
  73.  le=b-bc
  74.   if le then return mid s,bc,le
  75.   end method
  76.  
  77.   method instrword(sys i,string s,k) as sys
  78.   =========================================
  79.   do
  80.     w=getword s,i
  81.     if aa=0 then return 0
  82.     if w=k then return bc
  83.   end do
  84.   end method
  85.  
  86.   method instrwordce(sys i,string s,k) as sys
  87.   ===========================================
  88.   do
  89.     w=getword s,i
  90.     if aa=0 then return 0
  91.     if aa=58 then return i
  92.     if w=k then return i
  93.   end do
  94.   end method
  95.  
  96.   end class 'wordman
  97.  
  98.  
  99.  
  100.   ============
  101.   class buffer
  102.   ============
  103.   '
  104.  string br    'buffer string
  105.  sys    lb    'length of buffer
  106.  sys    chars 'accum char count
  107.  
  108.   method get() as string
  109.   ======================
  110.   return left br,chars
  111.   end method
  112.  
  113.   method append(string s)
  114.   =======================
  115.   sys a,le
  116.   le=len s
  117.   a=le+chars
  118.   if a>lb
  119.     br+=space(8192) 'stretch
  120.    lb+=8192
  121.   end if
  122.   mid (br,chars+1)=s
  123.   chars+=le
  124.   end method
  125.   '
  126.  end class
  127.  
  128.  
  129.  
  130.  
  131.  
  132.   ==============
  133.   class indenter
  134.   ==============
  135.  
  136.   has wordman wm 'text word utilities
  137.  has buffer  buf 'buffer to hold result
  138.  '
  139.  'SETTINGS
  140.  sys     instep  'indent step size
  141.  sys     lmargin 'left margin
  142.  'SHARED STATES
  143.  sys     lcount  'line counter
  144.  sys     dcount  'indent counter (test)
  145.  sys     embcmt  'embedded comment flag /* .. */
  146.  sys     indi    'indent relative
  147.  sys     indo    'indent accumulator
  148.  
  149.   method spacer(string t,s1,s2,sys n) as sys
  150.   ==========================================
  151.   sys a,b,c,le,i=1
  152.   b=wm.instrword i,t,s1
  153.   if b=1 'start of word
  154.    n*=instep 'create a new indent for the next line
  155.    if s2
  156.       b=wm.instrword i,t,s2 'block closing on same line
  157.    else
  158.       b=0
  159.     end if
  160.     '
  161.    if b then 'check for commented out end-blocks
  162.      if s2="then" then
  163.         b+=4
  164.         wm.skiplspace t,b
  165.         select asc t,b
  166.         case 0,39,59 : indi=n
  167.         end select
  168.       end if
  169.       a=wm.instrword 1,t,"'" : if a>0 and a<b then indi=n
  170.      a=wm.instrword 1,t,";" : if a>0 and a<b then indi=n
  171.     else
  172.       indi=n
  173.     end if 's2
  174.    if n=0 then indo-=instep : indi=instep 'else elseif case
  175.    if indi<0 then indo+=indi : indi=0
  176.     if indo<0 then indo=0 'clamp min indentation
  177.    'when indi>0 then the indent will be applied to the next line
  178.    return 1
  179.   end if 's1
  180.  end method
  181.  
  182.   method clean(string s) as string
  183.   ================================
  184.   sys a,i,e
  185.   string bu=s
  186.   e=len bu
  187.   do
  188.     i++
  189.     if i>e then exit do
  190.     a=asc bu,i
  191.     select a
  192.     case 13,10   : 'do not replace
  193.    case 0 to 31 : mid bu,i," " 'replace with space
  194.    end select
  195.   end do
  196.   return bu
  197.   end method
  198.  
  199.   method indent(string dat)
  200.   =========================
  201.   '
  202.  string cr=chr(13,10)
  203.   string tab=chr(9)
  204.   sys    a,b  'temp
  205.  sys    ex   'exit flag
  206.  sys    pu=1 'next line position
  207.  string s    'line string
  208.  string t    'line string lowercase
  209.  string bu   'cleaned dat
  210.  '
  211.  bu=clean dat
  212.   do
  213.     if ex then exit do
  214.     a=instr pu,bu,cr
  215.     if a=0 then ex=1 : a=1+len bu
  216.     '
  217.    s=mid bu,pu,a-pu  'extract line
  218.    pu=a+len(cr)      'skip cr
  219.    '
  220.    do 'redocmt:
  221.      '
  222.      s=ltrim rtrim s 'remove previous indents and endspace
  223.      t=lcase s       'view lowercase for keyword matching
  224.      '
  225.      if embcmt
  226.         a=instr t,"*/"
  227.         if a
  228.           embcmt=0
  229.         end if
  230.         exit do
  231.       else
  232.         if asc(t)=47
  233.           if asc(t,2)=42
  234.             b=instr(3,t,"*/")
  235.             if b
  236.               t=mid(s,b+2)
  237.               s=space(lmargin+indo)+left(s,b+1)
  238.               buf.append s
  239.               s=t
  240.               continue do 'look at rest of line again
  241.            else
  242.               embcmt=1
  243.             end if
  244.           end if
  245.         end if
  246.       end if
  247.       exit do
  248.     end do
  249.     '
  250.    if     spacer(t, "(", ")",1)
  251.     elseif spacer(t, "{", "}",1)
  252.     elseif spacer(t, "select", "",1)
  253.     elseif spacer(t, "sub", "",1)
  254.     elseif spacer(t, "function", "",1)
  255.     elseif spacer(t, "method", "",1)
  256.     elseif spacer(t, "methods", "",1)
  257.     elseif spacer(t, "type", "",1)
  258.     elseif spacer(t, "class", "",1)
  259.     elseif spacer(t, "macro", "",1)
  260.     elseif spacer(t, "def", "",1)
  261.     elseif spacer(t, "scope", "",1)
  262.     elseif spacer(t, "if", "then",1)
  263.     elseif spacer(t, "elseif", "",0)
  264.     elseif spacer(t, "else", "",0)
  265.     elseif spacer(t, "case", "",0)
  266.     elseif spacer(t, "for", "next",1)
  267.     elseif spacer(t, "do", "",1)
  268.     elseif spacer(t, "while", "",1)
  269.     elseif spacer(t, "end", "",-1)
  270.     elseif spacer(t, "endif", "",-1)
  271.     elseif spacer(t, "wend", "",-1)
  272.     elseif spacer(t, "next", "",-1)
  273.     elseif spacer(t, "endsel", "",-1)
  274.     elseif spacer(t, "}", "",-1)
  275.     end if
  276.     '
  277.    if s=""
  278.       s=cr
  279.     else
  280.       s=space(lmargin+indo)+s+cr
  281.       's=string(lmargin+indo," ")+s+cr
  282.    end if
  283.     '
  284.    buf.append s
  285.     indo+=indi
  286.     if indi>0 then dcount+=1
  287.     indi=0
  288.     lcount+=1
  289.   end do
  290.   end method
  291.   '
  292.  end class 'indenter
  293.  
  294.  
  295.   =====
  296.   'main
  297.  =====
  298.   '
  299.  '#recordof indenter
  300.  indenter id
  301.   id.instep=3  'indent step size
  302.  id.lmargin=2 'left margin
  303. 'id.indent getfile "in.txt"
  304.  id.indent getfile "ind1.o2bas"
  305.   putfile "out.bas",id.buf.get
  306.  'print "ok  " id.buf.chars "  bytes  " id.lcount " lines  " id.dcount " indents"
  307.  print id.buf.get
  308.  

Arnold

  • Guest
Re: How to test a class / method with OxygenBasic?
« Reply #6 on: February 26, 2015, 04:54:59 AM »
Hi Charles,

I found only a partial solution. In the old code I modified method append:
Code: [Select]
  method append(string s)
  =======================
  sys a,le
  le=len s
  a=le+chars
  if a>lb
    br+=space(8192) 'stretch
    lb+=8192
  end if

string s1=s
do
pos = instr(s1, chr(0))
if pos = 0 then exit do
s1 = left(s1,pos-1) & mid(s1, pos+1)
end do
mid (br,chars+1)=s1

  chars+=le
  end method

This is only to show that I tried it. The change deletes the 0 codes, but does not consider the indents in the next line. I also did not think about wide characters. I saw the 0x0020 in my editor, but I could not attribute it to wide character. The important aspect for me is that I tried to investigate a class / method the first time.

I tried the new indenter.o2bas of the updated OxygenBasic distribution with several files and these were indented ok. There is one thing which I do not know if it should be considered as missing:

e.g.:

  =============
  class wordman
    =============

    method skiplspace(s as string, i as sys)
      ========================================

  '--------------------------------------------------------------------
  Function WinMain(sys inst, prevInst, asciiz*cmdline, sys show) as sys
     '====================================================================


underscoring with some keywords will differ a little bit. I think this was already the case before. Nevertheless indenter.o2bas can be a very helpful tool.


Roland