meth Obj ==
  self eq: a
meth Obj !=
  self ne: a
meth Obj <
  self lt: a
meth Obj <=
  self le: a
meth Obj >
  self gt: a
meth Obj >=
  self ge: a

equals 23  
      1 + 22
equals 'hello'  
      ('h' ap: 'e') ap: ('l' ap: 'lo')
equals 'hello'  
      'he' ap: 'l' $ ap: 'lo'
equals 25  
      3 * 3 + 4 * 4

equals 142  
      m= Dict new. m at: 10 put: 100. (m at: 10) + 42
equals 142  
      m= Dict new. m at: 4 + 6 put: 10 * 10. (m at: 10) + 42

equals 'ok'    
      3 < 5   y::[ 'ok' ] n:: [ 'oops' ]
equals 'oops'    
      8 < 0 y::[ 'ok' ] n:: [ 'oops' ]
equals 'ok'    
      2 < 3   y::[ 'ok' ]
equals nil    
      8 < 0    y::[ 'ok' ]
equals nil    
      -8 < 0    n::[ 'ok' ]

equals 'Vec'
	Vec name

equals 4, 7, 9
    2 * 2; 7; 3 * 3;

equals 'Vec'
	() cls name
equals 0
	() len
equals 'Vec'
	(8;) cls name
equals 1
	(8;) len
equals 'Vec'
	(8,) cls name
equals 1
	(8,) len
equals 25
	x, y = Vec(3, 4).   x * x + y * y.
equals 26
	x, y = 3; 4.   x * x + y * y $ + 1.
equals 26
	x; y = 3, 4.   x * x + y * y $ + 1.

meth Vec eq:
  (a cls name equals: 'Vec')
    n: ['Vec.== expected Vec argument, but got' err: VEC(a, a cls, a cls name, a cls name equals: 'Vec') ]
    y: [
      self len == a len
        n: ['Vec.== got different length Vecs' err: VEC(self, a)]
        y: [
          z= Vec new.
          self len do: [i :
	    z append: ((self at: i) == (a at: i)).
          ].
          z
        ]
      ].

equals 1, 1, 0
  Vec('foo', 100, 'z') == Vec('foo'; 100; 'zoo')

meth Vec collect:
    "Goldberg & Robson, 1989. p215"
    z= self cls new.
    self do: [x :
      z ap: ( a value: x ) ] .
    z

equals VEC( 100, 400, 900. )
  VEC( 10, 20, 30. ) collect: [x :  x * x]

meth Vec select:
    "Goldberg & Robson, 1989. p216"
    z= self cls new .
    self do: [x : .
      ( a value: x ) y: [
        z ap: x ] ] .
    z

equals 10, 20
  ( 10, 20, 30. ) select: [x:  x < 25]

meth Vec join:
  sb= Buf new.
  front= 1.
  self do: [x:
    front y: [front= 0]
          n: [ sb ap: a].
    sb ap: x ].
  sb str.

meth Vec join
  self join: ' '
meth Vec jam
  self join: ''

meth Vec join:
  sb= Buf new.
  front= 1.
  self do: [x:
    front y: [front= 0]
          n: [ sb ap: a].
    sb ap: x str ].
  sb str.
meth Vec join
  self join: ' '
meth Vec jam
  self join: ''

equals Vec[33; 44]
  33, 44
equals Vec[33; 44; 55]
  33; 44; 50 + 4 $ + 1
equals Vec[Vec[22; 44]; 55]
  22, 44 ; 55

equals 'once-upon-a-time'
  ('once', 'upon', 'a', 'time') join: '-'
  
class App Usr
class Home App

meth HomeCls footerButtons
  Vec(
      '|link|/RESET|[RESET]|';
      '|link|/Home|[Home]|';
      '|link|/Browse|[Browse]|';
      '|link|/FormDoit|[Doit]|';
      '|link|/DrawLife|[DrawLife]|';
      '|link|/DrawLine|[DrawLine]|';
      '|link|/DrawRect|[DrawRect]|';
      '|link|/DrawStar|[DrawStar]|';
      '|link|/ListUnicodePages|[ListUnicodePages]|';
  )

meth Home handle:query:
  "Default class for handling ':'."

  Dict new  at: 'type' put: 'list'
          $ at: 'title' put: a
          $ at: 'value' put: (
          '|link|/Home|Home|', 'Go Home.';
          '|link|/Reset|Reset|', 'Reset Interpreter.';
          '|link|/Browse|browse|', 'Browse Classes.';
          '|link|/FormDoit|doit|', 'Evaluate code';
          '|link|/DrawLife|[DrawLife]|', 'Conway''s Life';
          '|link|/DrawLine|[DrawLine]|', 'Draw Line';
          '|link|/DrawRect|[DrawRect]|', 'Draw Rect';
          '|link|/DrawStar|[DrawStar]|', 'Draw Star';
          '|link|/ListUnicodePages|[ListUnicodePages]|', 'List Unicode Pages';
        ).


class Browse App
meth Browse handle:query:
  ww= a split: '.' .
  wl= ww len .
  clss= Cls all .

  "Start the list V with an UP link."
  v= Vec('|link|/Home|[Home]|', 'Go Home.';).
  v len == 1 $must: (v, '#1').
  v at: 0 $len == 2 $must: (v, '#2').

  ( wl == 1 ) y: [
    "gk are Good Keys, those that are classes."
    gk= clss dir select: [i:
        AND( clss at: i $ cls name ends: 'Cls';
             OR( clss at: i $ name ends: 'Cls' $ not;
                 clss at: i $ cls name == 'ClsCls' ) )
    ].

    gk do: [k:
        kc= clss at: k .
        kn= kc name .
        tmp = ('|link|/Browse.', kn, '|', kn, '|') jam, kc meths join: ' '.
	tmp len == 2 $must: (tmp, '#3').
        v ap: tmp.
	v do: [each: each len == 2 $must: (v, each, '#4')].
    ].

    z= Dict new
        $ at: 'type' put: 'list'
        $ at: 'title' put: 'Browsing All Classes'
        $ at: 'extra' put: ( clss )
        $ at: 'extraKeys' put: ( clss dir )
        $ at: 'extraCollect' put: ( clss dir collect: [i:  ( clss at: i ) cls cls name ] )
        $ at: 'extraSelect' put: gk
        $ at: 'value' put: v
	.

  ] .
  
  ( wl == 2 ) y: [
    cn= ww at: 1 .  "class name"
    co= clss at: cn toLower .   "class object"

    d= co cls methDefs .
    d dir do: [x:  "For each class method"
      v ap: ( ( '|link|/EditMethod.', cn, 'Cls.', x, '|class ', x, '|' ) jam, d at: x $ str ) .
    ] .

    d= co methDefs .
    d dir do: [x:   "For each instance method"
      v ap: ( ( '|link|/EditMethod.', cn, '.', x, '|', x, '|' ) jam, d at: x $ str ) .
    ] .

    z= Dict new  at: 'type' put: 'list'
          $ at: 'title' put: ( 'Browsing Class' ap: cn )
          $ at: 'value' put: v
        .

  ] .
  z .


class EditMethod App
meth EditMethod handle:query:
  ww= a split: '.' .
  wl= ww len .
  clss= Cls all .

  ( wl ne: 3 ) y: [ Zork foo ] .

  cn= ww at: 1 .  "class name"
  mn= ww at: 2 .  "method name"

  co= clss at: cn toLower .   "class object"
  mo= co methDefs at: mn .  "method object"

  z= Dict new  at: 'type' p: 'edit'
          $ at: 'title' p: ( 'Editing Class' ap: cn $ ap: ' Method ' $ ap: mn )
          $ at: 'value' p: ( mo str )
          $ at: 'action' p: ( '/SubmitMethod' )
          $ at: 'field1' p: 'ClassName'
          $ at: 'value1' p: cn
          $ at: 'field2' p: 'MethodName'
          $ at: 'value2' p: mn
        .
  z .


class SubmitMethod App
meth SubmitMethod handle:query:

  clss= Cls all .

  cname= b at: 'ClassName' .
  mname= b at: 'MethodName' .

  co= clss at: cname tolower .

  z= co definemethod: mname abbrev: '' doc: '' code: ( b at: 'text' ) .

  DICT(
    'type', 'list';
    'title', ( 'Submitted Class', cname, ' Method ', mname ) join;
    'value', Vec( Vec('|link|/Home|Home|';  'Home.'; ) );
    'URL', a;
    'QUERY', b;
    'Z', z;
  ).

class FormDoit App
meth FormDoit handle:query:
  DICT(
    'type', 'edit';
    'title', 'Doit Form';
    'value', '';
    'action', '/SubmitDoit';
  ).


class SubmitDoit App
meth SubmitDoit handle:query:
  
  z= Tmp new eval: ( b at: 'text' ).

  DICT(
    'type', 'text';
    'title', 'doit: ' ap: (b at: 'text');
    'value', z str;
  ).


class DrawLine App
#meth DrawLine handle:query:
#  DICT[ 'type'; 'draw'.
#	'title'; 'Drawing a line'.
#	'value'; Vec[
#           Vec[ 'line'. 10. 400. 50. 300. 2 ].
#	].
#	'width'; 300.
#	'height'; 500.
#  ]
#
class DrawStar App
#meth DrawStar handle:query:
#  ex, ey = b at: 'ex'; b at: 'ey'. "Event location."
#  ex ifNil: [ex = 300] ifNotNil: [ex = ex num].
#  ey ifNil: [ey = 300] ifNotNil: [ey = ey num].
#
#  v = 100 range collect: [i:  theta = i fdiv: 10 .
#      x= theta sin * 290 $+ 300.
#      y= theta cos * 290 $+ 300.
#      VEC[ 'line'. ex. ey. x. y. ]. "Line command."
#  ] .
# 
#  DICT[ 'type'; 'draw'.
#	'title'; 'Drawing a line'.
#	'value'; v.
#	'width'; 600.
#	'height'; 600.
#  ].
#
class DrawLife App
#meth DrawLife canX
#  900
#meth DrawLife canY
#  500
#meth DrawLife numX
#  27
#meth DrawLife numY
#  15
#meth DrawLife delX
#  self canX idiv: self numX
#meth DrawLife delY
#  self canY idiv: self numY
#meth DrawLife initP
#  self numX range collect: [x:
#    self numY range collect: [y:
#      t = x + y * 13 .
#      o = OR[(t imod: 4) == 0.
#         (t imod: 5) == 0.
#         (t imod: 7) == 0.].
#    ]
#  ] $ say.
#
#meth DrawLife draw
#
#  "Jam[ 'Instance id='. self usrId str. ' hash='. self hash str. ] say: p."
#  p ifNil: [ p = self initP ].
# 
#  "tDebug = self numX range collect: [x:
#        self numY range collect: [y:
#           nei = 0.
#           3 do: [i:  i = i mi: 1 + x.
#             3 do: [j:  j = j mi: 1 + y.
#               nei = nei + ((p at: i) at: j).
#             ].
#           ].
#           nei.
#        ].
#      ].
#  tDebug say.  "
#
#  nextP = self numX range collect: [x:
#        self numY range collect: [y:
#           nei = 0.
#           3 do: [i:  i = i - 1 + x.
#             3 do: [j:  j = j - 1 + y.
#               nei = nei + ((p at: i) at: j).
#             ].
#           ].
#           (p at: x) at: y $
#               n: [ nei == 3 ]
#               y: [ OR[nei == 3.  nei == 4.] ].
#        ].
#      ].
#  p = nextP.
#  v = Vec new.
#  self numX do: [x:
#    self numY do: [y:
#      (p at: x) at: y $
#        y: [
#             xx = x * self delX + (self delX idiv: 2).
#             yy = y * self delY + (self delY idiv: 2).
#             v ap: Vec[ 'rect'.  xx - 6.  yy - 6. 12. 12.].
#        ]
#        n: [
#             xx = x * self delX + (self delX idiv: 2).
#             yy = y * self delY + (self delY idiv: 2).
#             v ap: Vec[ 'line'.  xx - 2.  yy - 2.
#                                 xx + 2.  yy + 2.].
#        ].
#    ].
#  ].
#  v.
#
#meth DrawLife handle:query:
#  DICT[
#    'type'; 'draw'.
#    'width'; self canX.
#    'height'; self canY.
#    'value'; self draw.
#    'url'; JAM[ '/'. self cls name. '.'. self usrId str. ].
#  ].
#
class DrawRect App
#meth DrawRect handle:query:
#  v = Vec new.
#  10 do: [x:
#    10 do: [y:
#      v ap: ('rect', 80 * x, 70 * y, 20, 15, 2, 'green').
#      v ap: ('text', 80 * x + 25, 70 * y + 30, JAM[x str. ','. y str] ).
#      ]].
#  DICT[ 'type'; 'draw'.
#	'title'; 'Drawing 100 Rectangles'.
#	'value'; v.
#	'width'; 300.
#	'height'; 500.
#  ]
#
#
class ListUnicodePages App
#meth ListUnicodePages handle:query:
#  ww= a split: '.' .
#  ( ww len == 2 ) 
#      y: [ self drawPage: (ww at: 1) num ]
#      n: [ self listPages ]
#
#
#meth ListUnicodePages listPages
#  v = 100 range collect: [ i:
#    link = Jam['|link|/ListUnicodePages.'. i str. '|Page '. i str. '|'].
#    label = Jam[ 'Page '. i str. ].
#    (link, label).
#  ].
#  DICT[ 'type'; 'list'.
#	'title'; 'Unicode Pages.'
#	'value'; v.
#  ].
#  
#
#meth ListUnicodePages drawPage:
#  txt = Implode[ 256 range collect: [ i: 
#    i = i + a * 256.
#    (i str, ' [', i, '] ').
#  ]].
#  DICT[ 'type'; 'text'.
#	'title'; 'Unicode Page ' ap: a str.
#	'value'; txt.
#  ].
#
