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
meth Blk tuple
  self vec
meth Blk list
  self vec

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 1
	'Vec' == Vec name

equals VEC[ 4. 7. 9. ]
    VEC[ 2 * 2. 7. 3 * 3. ]

equals 'Vec'
	() cls name
equals 0
	() 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.

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 Vec[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 run: 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 run: x ) y: [
        z ap: x ] ] .
    z

equals VEC[ 10. 20. ]
  VEC[ 10. 20. 30. ] select: [:x.  x < 25]

meth Blk join:
  sb= Buf new.
  front= 1.
  self vec do: [ :x .
    front y: [front= 0]
          n: [ sb ap: a].
    sb ap: x ].
  sb str.
meth Blk join
  self join: ' '
meth Blk 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: '-'
  
meth Vec tuple
  self vec
meth Vec list
  self vec

class App Usr
class Home App

meth HomeCls footerButtons
  Vec[
      '|link|/RESET|[RESET]|'.
      '|link|/Home|[Home]|'.
      '|link|/Browse|[Browse]|'.
      '|link|/FormDoit|[Doit]|'.
      '|link|/FormDoit2|[Doit2]|'.
      '|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: VEC[
          '|link|/Home|Home|', 'Go Home.'.
          '|link|/Reset|Reset|', 'Reset Interpreter.'.
          '|link|/Browse|browse|', 'Browse Classes.'.
          '|link|/FormDoit|doit|', 'Evaluate code'.
          '|link|/FormDoit2|doit2|', 'Evaluate code, Syntax 2'.
          '|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= [ '|link|/Home|[Home]|', 'Go Home.' ] vec .

  ( 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 .
        v ap: ( JAM['|link|/Browse.' . kn . '|' . kn . '|']; kc meths join: ' ' ) .
        ] .



    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: ( Jam[ '|link|/EditMethod.' . cn . 'Cls.' . x . '|class ' . x. '|' ]; d at: x ,, str ) .
    ] .

    d= co methDefs .
    d dir do: [ :x . "For each instance method"
      v ap: ( Jam[ '|link|/EditMethod.' . cn . '.' . x . '|' . x. '|' ]; 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:
  'SubmitMethod << url' say: a.
  'SubmitMethod << query' say: b.
  'SubmitMethod << OK' say.

  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', Join[ 'Submitted Class'. cname. ' Method '. mname ].
	'value', Vec[ Vec[ '|link|/Home|Home|'.  'Home.' ] ].
	'URL', a.
	'QUERY', b.
	'Z', z.
  ].

  " Browse new handle: JAM{'Browse.'. cname} query: DICT(). "


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


class SubmitDoit App
meth SubmitDoit handle:query:
  'SubmitDoit << url' say: a.
  'SubmitDoit << query' say: b.
  'SubmitDoit << OK' say.
  
  z= Tmp new eval: ( b at: 'text' ).
  DICT[ 'type'; 'text'.
       'title'; [ 'doit:'. ( b at: 'text' ) str ] join: ' '.
       'value'; z str.
  ].

class FormDoit2 App
meth FormDoit2 handle:query:
  DICT[ 'type'; 'edit'.
       'title'; 'Doit2 Form (New Syntax)'.
       'value'; ''.
       'action'; '/SubmitDoit2'.
  ].


class SubmitDoit2 App
meth SubmitDoit2 handle:query:
  'SubmitDoit2 << url' say: a.
  'SubmitDoit2 << query' say: b.
  'SubmitDoit2 << OK' say.
  
  z= Tmp new eval2: ( b at: 'text' ).
  DICT[ 'type'; 'text'.
       'title'; [ 'doit2:'. ( b at: 'text' ) str ] join: ' '.
       '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 iota 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 iota collect: [ :x
    self numY iota 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 iota collect: [ :x.
        self numY iota 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 iota collect: [ :x.
        self numY iota 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 iota 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 iota collect: [ :i. 
    i = i + a * 256.
    (i str, ' [', i, '] ').
  ]].
  DICT[ 'type'; 'text'.
	'title'; 'Unicode Page ' ap: a str.
	'value'; txt.
  ].


