source: to-imperative/trunk/compiler/rfp_asail_java.rf @ 1825

Last change on this file since 1825 was 1825, checked in by orlov, 15 years ago
  • Added proper generation of imports in Java code.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.2 KB
Line 
1// $Id: rfp_asail_java.rf 1825 2005-12-29 01:57:15Z orlov $
2
3$use Apply Arithm Box Class Compare Convert JavaMangle List StdIO Table;
4$use "rfpc";
5$use "rfp_helper";
6
7$box Int;
8
9$box Exports;
10
11$table Inputs;
12
13$box Module-Name;
14
15$box Entry;
16
17$box Entry-Name;
18
19$box Current-Namespace;
20
21$box Func-Name;
22
23$box Return-Type;
24
25$box Ress;
26
27$table Iter-Vars;
28
29$func ASAIL-To-Java e.body = e.java-code;
30
31$func Expr-To-Java (e.ASAIL-Expr-init ) e.ASAIL-Expr-rest = e.aux-arrays (e.java-expr);
32
33$func Expr-Ref-To-Java e.ASAIL-Expr-Ref = e.aux-arrays (e.JAVA-Expr-Ref);
34
35$func Expr-Int-To-Java s.acc e.ASAIL-Expr-Int = e.JAVA-Expr-Int;
36
37$func Step-To-Java e.step-operators = e.java-step-operators;
38
39$func Const-Expr-To-Java e.ASAIL-const-expr = e.aux-arrays (e.JAVA-const-expr);
40
41$func Expr-Args-To-Java e.args = e.aux-arrays (e.java-args);
42
43$func Int-Args-To-Java s.acc e.args = e.java-args;
44
45$func Var-Args-To-Java e.args = e.java-args;
46
47$func Symbol-To-Java s.RFP-Symbol = e.JAVA-String;
48
49$func Name-To-Java t.name = e.JAVA-Name;
50
51$func Cond-To-Java s.acc e.cond = e.JAVA-Cond;
52
53$func Infix-To-Java s.acc s.func-for-converting-args-to-java s.op e.args = e.java-expr;
54
55$func Op-Arg-To-Java s.op = s.func-for-converting-args-to-java;
56
57$func Access-Mode t.name = e.java-access-mode;
58
59$box Free-Idx;
60
61$func Free-Index = e.free-index;
62
63$func Copy-Args (e.args) (e.ress) = (e.valid-args) e.subst;
64
65RFP-ASAIL-To-Java (e.ModuleName) (e.exports) e.asail =
66  <RFP-Clear-Table &Iter-Vars>,
67  {
68    <Store &Int <Lookup &RFP-Options INT>>;
69    <Store &Int Integer>;
70  },
71  <Store &Exports e.exports>,
72  <Store &Current-Namespace e.ModuleName>,
73  <Store &Entry (e.ModuleName Main)>,
74  <Store &Entry-Name /*empty*/>,
75  {
76    <ASAIL-To-Java e.asail> : v.java,
77      {
78        <? &Entry-Name> : v.name =
79          ('public static void main(java.lang.String[] args) {'
80            (('try {' (v.name' (new Expr ());') '}')
81             ('catch (RefalException e) {' ('System.out.println ("$error: " + e);') '}')
82            )
83          '}');;
84      } :: e.entry,
85      <Store &Module-Name <Rfp2Java e.ModuleName>>,
86      (<Domain &Inputs>)
87      ('public class '<? &Module-Name>' {'
88        (v.java e.entry)
89       '}');
90    ();
91  };
92
93ASAIL-To-Java e.asail, {
94  e.asail : t.item e.rest, t.item : {
95    (s.tag t.name (e.args) (e.ress) e.body),
96      s.tag : \{
97        FUNC  = ('void') /*empty*/;
98        FUNC? = ('boolean') ('return true;');
99      } :: (e.return-type) e.return =
100      <Store &Free-Idx>,
101      <Store &Return-Type e.return-type>,
102      <Store &Ress e.ress>,
103      { <? &Entry> : t.name = <Store &Entry-Name <Rfp2Java t.name>>;; },
104//      <RFP-Extract-Qualifiers t.name> :: (e.qualifiers) e.n,
105      <Store &Func-Name <Name-To-Java t.name>>,
106      ('static '<Access-Mode t.name>' 'e.return-type' '
107        <? &Func-Name>' ('<Var-Args-To-Java e.args e.ress>') throws RefalException')
108        ('{' (<ASAIL-To-Java e.body> e.return) '}');
109    (IF (e.cond) e.body) =
110      {
111        e.cond : (CALL t.name (e.args) (e.ress)) =
112          <Copy-Args (e.args) (e.ress)> :: (e.args) e.subst,
113          <Expr-Args-To-Java e.args <Paren e.ress>> :: e.arrays (e.args),
114          e.subst e.arrays (<Name-To-Java t.name>' ('e.args')') ();
115        <Box> :: s.acc =
116          /*empty*/ (<Cond-To-Java s.acc e.cond>) (<? s.acc>);
117      } :: e.subst (e.cond) (e.arrays),
118      e.subst e.arrays
119      ('if ('e.cond')')
120      ('{' (<ASAIL-To-Java e.body>) '}');
121    (FOR (e.cont-label) (e.break-label) (e.cond) (e.step) e.body) =
122      {
123        e.cont-label : t = <Rfp2Java (LABEL e.cont-label)> ': ';;
124      } :: e.cont,
125      {
126        e.break-label : t = <Rfp2Java (LABEL e.break-label)> ': ';;
127      } :: e.break,
128      <Box> :: s.acc,
129      <Cond-To-Java s.acc e.cond> :: e.cond,
130      <? s.acc>
131      (e.cont e.break 'for ( ; 'e.cond'; '<Step-To-Java e.step>')')
132        ('{' (<ASAIL-To-Java e.body>) '}');
133    (LABEL (e.label) e.body) =
134      (<Rfp2Java (LABEL e.label)>': {' (<ASAIL-To-Java e.body>) '}');
135    (TRY e.body) =
136      ('try') ('{' (<ASAIL-To-Java e.body>) '}');
137    (CATCH-ERROR e.body) =
138      ('catch (RefalException error) {'
139        ('Expr err = error.getExpr ();')
140        (<ASAIL-To-Java e.body>)
141       '}');
142    RETFAIL = ('return false;');
143    FATAL =
144      ('throw new RefalException ("'<? &Module-Name>'", "'<? &Func-Name>'", "Unexpected fail");');
145    (LSPLIT t.name (e.min) t.var1 t.var2) =
146      <Rfp2Java t.name> :: e.n,
147      '_va_' <Free-Index> :: e.new-var,
148      <Bind &Iter-Vars (t.name) (e.new-var)>,
149      <Box> :: s.acc,
150      <Expr-Int-To-Java s.acc e.min> :: e.min,
151      <? s.acc>
152      ('Expr.SplitIterator 'e.new-var' = 'e.n'.leftSplit('e.min');')
153      ('Expr '<Rfp2Java t.var1>' = 'e.new-var'.getLeft();')
154      ('Expr '<Rfp2Java t.var2>' = 'e.new-var'.getRight();');
155    (RSPLIT t.name (e.min) t.var1 t.var2) =
156      <Rfp2Java t.name> :: e.n,
157      '_va_' <Free-Index> :: e.new-var,
158      <Bind &Iter-Vars (t.name) (e.new-var)>,
159      <Box> :: s.acc,
160      <Expr-Int-To-Java s.acc e.min> :: e.min,
161      <? s.acc>
162      ('Expr.SplitIterator 'e.new-var' = 'e.n'.rightSplit('e.min');')
163      ('Expr '<Rfp2Java t.var1>' = 'e.new-var'.getLeft();')
164      ('Expr '<Rfp2Java t.var2>' = 'e.new-var'.getRight();');
165    (ASSIGN t.var e.expr) =
166      <Expr-To-Java () e.expr> :: e.a (e.j-expr),
167      {
168        <? &Ress> : e t.var e =
169          e.a (<Rfp2Java t.var>'.assign('e.j-expr');');
170        e.a (<Rfp2Java t.var>' = 'e.j-expr';');
171      };
172    (DECL s.type t.var) =
173      (s.type' '<Rfp2Java t.var>' = new Expr ();');
174    (INT t.var e.expr) =
175      <Box> :: s.acc,
176      <Expr-Int-To-Java s.acc e.expr> :: e.expr,
177      <? s.acc> ('int '<Rfp2Java t.var>' = 'e.expr';');
178    (EXPR t.var e.expr) =
179      <Expr-Ref-To-Java e.expr> :: e.a (e.j-expr),
180      e.a ('Expr '<Rfp2Java t.var>' = new Expr ('e.j-expr');');
181    (DEREF t.var e.expr (e.pos)) =
182      <Expr-Ref-To-Java e.expr> :: e.a (e.j-expr),
183      <Box> :: s.acc,
184      <Expr-Int-To-Java s.acc e.pos> :: e.pos,
185      e.a <? s.acc> ('Expr '<Rfp2Java t.var>' = new Expr ('e.j-expr', 'e.pos');');
186    (SUBEXPR t.var e.expr (e.pos) (e.len)) =
187      <Expr-Ref-To-Java e.expr> :: e.a (e.j-expr),
188      <Box> :: s.acc,
189      <Expr-Int-To-Java s.acc e.pos> :: e.pos,
190      <Expr-Int-To-Java s.acc e.len> :: e.len,
191      e.a <? s.acc> ('Expr '<Rfp2Java t.var>' = new Expr ('e.j-expr', 'e.pos', 'e.len');');
192    (DROP t.var) =
193      (<Rfp2Java t.var>'.drop ();');
194    (CONTINUE t.label) =
195      ('continue '<Rfp2Java (LABEL t.label)>';');
196    (BREAK t.label) =
197      ('break '<Rfp2Java (LABEL t.label)>';');
198    (ERROR e.expr) =
199      <Expr-Ref-To-Java e.expr> :: e.a (e.j-expr),
200      e.a ('throw new RefalException ('e.j-expr');');
201    (CONSTEXPR s.linkage t.name (e.comment) e.expr) =
202      {
203        t.name : (STATIC e) = <Rfp2Java t.name>;
204        //<RFP-Extract-Qualifiers t.name> :: (e.qualifiers) e.name = e.name;
205        <Name-To-Java t.name>;
206      } :: e.n,
207      <Const-Expr-To-Java e.expr> :: e.a (e.j-expr),
208      e.a ('static '<Access-Mode t.name>' final Expr 'e.n' = 'e.j-expr';');
209    (OBJ s.linkage s.tag t.name) =
210      <To-Chars s.tag> : s1 e2,
211      <RFP-Extract-Qualifiers t.name> :: (e.qualifiers) e.n,
212      ('static '<Access-Mode t.name>' final Expr '<Name-To-Java t.name>
213        ' = new Expr (new Named' s1 <To-Lower e2>' ("'e.n'"));');
214    (DECL-OBJ t.name) = ;
215    (DECL-FUNC t.name) = ;
216    /*
217     * s.call can be CALL or TAILCALL
218     */
219    (s.call t.name (e.args) (e.ress)) =
220      <Copy-Args (e.args) (e.ress)> :: (e.args) e.subst,
221      <Expr-Args-To-Java e.args <Paren e.ress>> :: e.arrays (e.args),
222      <Name-To-Java t.name>' ('e.args');' :: e.c,
223      {
224        s.call : TAILCALL, <? &Return-Type> : 'boolean' =
225          e.subst e.arrays ('return 'e.c);
226        e.subst e.arrays (e.c);
227      };
228  } :: e.java-item,
229    e.java-item <ASAIL-To-Java e.rest>;
230  /*empty*/;
231};
232
233Copy-Args (e.args) (e.ress) =
234  (e.args) (/*e.valid-args*/) /*e.subst*/ $iter {
235    e.args : (e1) e2, {
236      e.ress : e (e1) e =
237        '_va_' <Free-Index> :: e.new-var,
238        (e2) (e.valid-args (e.new-var))
239            e.subst ('Expr 'e.new-var' = new Expr('<Rfp2Java e1>');');
240      (e2) (e.valid-args (e1)) e.subst;
241    };
242  } :: (e.args) (e.valid-args) e.subst,
243  e.args : /*empty*/ =
244  (e.valid-args) e.subst;
245
246/*
247 * Determine type of e.expr - int or Refal.
248 */
249Expr-To-Java (e.init) e.expr-all, e.expr-all : {
250  /*empty*/ = <Expr-Ref-To-Java e.init>;
251  (PAREN e.expr) e.rest = <Expr-Ref-To-Java e.init e.expr-all>;
252  (EXPR e.expr) e.rest = <Expr-Ref-To-Java e.init e.expr-all>;
253  (DEREF e.expr) e.rest = <Expr-Ref-To-Java e.init e.expr-all>;
254  (SUBEXPR e.expr) e.rest = <Expr-Ref-To-Java e.init e.expr-all>;
255  (LENGTH e.expr) e.rest = (<Expr-Int-To-Java XXX e.init e.expr-all>);
256  (MAX e.args) e.rest = (<Expr-Int-To-Java XXX e.init e.expr-all>);
257  (MIN e.args) e.rest = (<Expr-Int-To-Java XXX e.init e.expr-all>);
258  (INFIX s.op e.args) e.rest = (<Expr-Int-To-Java XXX e.init e.expr-all>);
259  (s.var-tag (e.QualifiedName)) e.rest =
260    <Expr-To-Java (e.init (s.var-tag (e.QualifiedName))) e.rest>;
261};
262
263$func Term-Ref-To-Java s.acc term = e.term;
264
265Expr-Ref-To-Java {
266  /*empty*/ = ('Expr.empty');
267  term =
268    <Box> :: s.acc,
269    <Term-Ref-To-Java s.acc term> :: e.term,
270    <? s.acc> (e.term);
271  t1 t2 =
272    <Box> :: s.acc,
273    <Term-Ref-To-Java s.acc t1> :: e.t1,
274    <Term-Ref-To-Java s.acc t2> :: e.t2,
275    <? s.acc> ('new Expr ('e.t1', 'e.t2')');
276  expr =
277    '_va_'<Free-Index> :: e.new-var,
278    <Box> :: s.acc,
279    <Infix-To-Java s.acc &Term-Ref-To-Java "," <Paren expr>> :: e.arr-init,
280    <? s.acc>
281    ('Expr[] 'e.new-var' = { 'e.arr-init' };')
282    ('Expr.concat ('e.new-var')');
283};
284
285Term-Ref-To-Java s.acc term = term : {
286  (PAREN e.expr) =
287    <Expr-Ref-To-Java e.expr> :: e.a (e.j-expr),
288    <Put s.acc e.a>,
289    'new Expr('e.j-expr')';
290  (DEREF e.expr (e.pos)) =
291    <Expr-Ref-To-Java e.expr> :: e.a (e.j-expr),
292    <Put s.acc e.a>,
293    <Expr-Int-To-Java s.acc e.pos> :: e.pos,
294    'new Expr ('e.j-expr', 'e.pos')';
295  (SUBEXPR e.expr (e.pos) (e.len)) =
296    <Expr-Ref-To-Java e.expr> :: e.a (e.j-expr),
297    <Put s.acc e.a>,
298    <Expr-Int-To-Java s.acc e.pos> :: e.pos,
299    <Expr-Int-To-Java s.acc e.len> :: e.len,
300    'new Expr ('e.j-expr', 'e.pos', 'e.len')';
301  (REF t.name) = <Name-To-Java t.name>;
302  ERROR-EXPR = 'err';
303  (s.var-tag t.name) = <Rfp2Java (s.var-tag t.name)>;
304};
305
306Expr-Int-To-Java s.acc expr = expr : {
307//  /*empty*/ = /*empty*/;
308  s.ObjectSymbol =
309    {
310      <Int? s.ObjectSymbol> = s.ObjectSymbol;
311      $error ("Illegal int-symbol: " s.ObjectSymbol);
312        //FIXME: надо проверять, что число не
313        //       выходит за допустимые границы.
314        //       Задавать эти границы опциями.
315    };
316  (LENGTH e.expr) =
317    <Expr-Ref-To-Java e.expr> :: e.a (e.j-expr),
318    <Put s.acc e.a>,
319    e.j-expr'.getLen ()';
320  (MAX e.args) =
321    'java.lang.Math.max ('<Int-Args-To-Java s.acc e.args>')';
322  (MIN e.args) =
323    'java.lang.Math.min ('<Int-Args-To-Java s.acc e.args>')';
324  (INFIX s.op e.args) =
325    '(' <Infix-To-Java s.acc &Expr-Int-To-Java s.op e.args> ')';
326//  (REF t.name) = <Name-To-Java t.name>;
327  (s.var-tag t.name) = <Rfp2Java (s.var-tag t.name)>;
328  expr = '(' <Infix-To-Java s.acc &Expr-Int-To-Java "+" <Paren expr>> ')';
329};
330
331Cond-To-Java s.acc expr = expr : {
332  /*empty*/ = /*empty*/;
333  (SYMBOL? e.expr (e.pos)) =
334    <Expr-Ref-To-Java e.expr> :: e.a (e.j-expr),
335    <Put s.acc e.a>,
336    e.j-expr'.symbolAt ('<Expr-Int-To-Java s.acc e.pos>')';
337  (CHECK-ITER e.expr) =
338    <Lookup &Iter-Vars e.expr>'.isValid ()';
339  (EQ e.expr1 (e.expr2) (e.pos)) =
340    <Expr-Ref-To-Java e.expr1> :: e.a1 (e.j-expr1),
341    <Expr-Ref-To-Java e.expr2> :: e.a2 (e.j-expr2),
342    <Put s.acc e.a1 e.a2>,
343    e.j-expr1'.eq ('e.j-expr2', '<Expr-Int-To-Java s.acc e.pos>')';
344  (TERM-EQ e.expr1 (e.expr2) (e.pos)) =
345    <Expr-Ref-To-Java e.expr1> :: e.a1 (e.j-expr1),
346    <Expr-Ref-To-Java e.expr2> :: e.a2 (e.j-expr2),
347    <Put s.acc e.a1 e.a2>,
348    e.j-expr1'.eq ('e.j-expr2', '<Expr-Int-To-Java s.acc e.pos> ')';
349  (NOT e.cond) =
350    '!' <Cond-To-Java s.acc e.cond>;
351  (INFIX s.op e.args) =
352    '(' <Infix-To-Java s.acc <Op-Arg-To-Java s.op> s.op e.args> ')';
353  expr = '(' <Infix-To-Java s.acc &Cond-To-Java "&&" <Paren expr>> ')';
354};
355
356Infix-To-Java s.acc s.arg2java s.op e.args, {
357  e.args : (e.arg) e.rest =
358    <Apply s.arg2java s.acc e.arg> :: e.arg,
359    <Infix-To-Java s.acc s.arg2java s.op e.rest> :: e.rest,
360    {
361      e.arg : v, e.rest : v = e.arg ' ' s.op ' ' e.rest;
362      e.arg e.rest;
363    };;
364};
365
366Op-Arg-To-Java s.op, {
367  s.op : \{ "&&"; "||"; } =
368    &Cond-To-Java;
369  s.op : \{ "<"; ">"; "<="; ">="; "=="; "!="; "+"; "-"; "%"; "*"; "/"; } =
370    &Expr-Int-To-Java;
371};
372 
373Step-To-Java {
374  /*empty*/ = /*empty*/;
375  (INC-ITER e.expr) = <Lookup &Iter-Vars e.expr>'.next ()';
376  (DEC-ITER e.expr) = <Lookup &Iter-Vars e.expr>'.prev ()';
377};
378
379$func Const-Expr-Aux e.expr = (e.arrays) e.java-expr;
380
381Const-Expr-To-Java {
382  /*empty*/ = ('empty');
383  (SUBEXPR t.name s.pos s.len) = ('new Expr ('<Rfp2Java t.name>', 's.pos', 's.len')');
384                  //FIXME: надо проверять, что s.pos и s.len
385                  //       не превышают допустимых величин.
386                  //       Задавать эти величины опциями.
387  e.expr =
388    <Const-Expr-Aux () e.expr> : {
389      (e.arrays) (e1)      = e.arrays (e1);
390      (e.arrays) (e1) (e2) = e.arrays ('new Expr ('e1', 'e2')');
391    };
392};
393
394Const-Expr-Aux (e.accum) e.expr, {
395  e.expr : s.sym e.rest, <Char? s.sym> =
396    <Const-Expr-Aux (e.accum <Symbol-To-Java s.sym>) e.rest>;
397  e.accum : v =
398    <Const-Expr-Aux () e.expr> :: (e.arrays) e.j-expr,
399    (e.arrays) ('Expr.fromSequence ("'e.accum'")') e.j-expr;
400  e.expr : t.item e.rest, t.item : {
401    (PAREN e.paren-expr) =
402      <Const-Expr-To-Java e.paren-expr> :: e.arrays (e.j-expr),
403      (e.arrays) ('new Expr ('e.j-expr')');
404    (REF t.name) =
405      () (<Name-To-Java t.name>);
406    (STATIC e) =
407      () (<Rfp2Java t.item>);
408//    (FUNC t.name) =
409//      '.concat (new Expr (new Reference ("'<Name-To-JAVA t.name>'")));
410//       static { Reference.defineReferable('<Rfp2Java e.varName>',
411//             new org.refal.j.Function("") {
412//             public boolean eval(Expr e1, Expr e2) throws Exception {
413//                 return '<Name-To-JAVA t.name>'(e1, e2);
414//             }
415//             });
416//             }//';
417    s.sym, {
418      <Int? s.sym> =
419        () ('new Expr (new '<? &Int>'('s.sym'))');
420      <Word? s.sym> =
421        () ('new Expr ("'<Symbol-To-Java s.sym>'")');
422    };
423  } :: (e.arrays) e.java-item =
424    <Const-Expr-Aux () e.rest> :: (e.new-arrays) e.java-rest,
425    (e.arrays e.new-arrays) e.java-item e.java-rest;
426  = () /*empty*/;
427};
428
429Symbol-To-Java s.ObjectSymbol, {
430  <To-Chars s.ObjectSymbol> () $iter {
431    e.symbol : s.char e.rest, s.char : {
432      '\\' = '\\\\';
433      '\n' = '\\n';
434      '\t' = '\\t';
435//        '\v' = '\\v';
436//        '\b' = '\\b';
437      '\r' = '\\r';
438//        '\f' = '\\f';
439      '\"' = '\\"';
440//      '\'' = '\\\'';
441      s = s.char;
442    } :: e.java-char,
443    e.rest (e.java-symbol e.java-char);
444  } :: e.symbol (e.java-symbol),
445    e.symbol : /*empty*/ =
446    e.java-symbol;
447};
448
449Int-Args-To-Java s.acc e.args =
450  e.args (/*e.java-args*/) $iter {
451    e.args : (e.arg) e.rest =
452      {
453        e.rest : v = ', ';
454        /*empty*/;
455      } :: e.comma,
456      e.rest (e.java-args <Expr-Int-To-Java s.acc e.arg> e.comma);
457    } :: e.args (e.java-args),
458  e.args : /*empty*/ =
459  e.java-args;
460
461Var-Args-To-Java e.args =
462  e.args (/*e.java-args*/) $iter {
463    e.args : t.arg e.rest =
464      {
465        e.rest : v = ', ';
466        /*empty*/;
467      } :: e.comma,
468      e.rest (e.java-args 'Expr '<Rfp2Java t.arg> e.comma);
469    } :: e.args (e.java-args),
470  e.args : /*empty*/ =
471  e.java-args;
472
473Expr-Args-To-Java e.args =
474  e.args (/*e.java-args*/) (/*e.arrays*/) $iter {
475    e.args : (e.arg) e.rest =
476      {
477        e.rest : v = ', ';
478        /*empty*/;
479      } :: e.comma,
480      <Expr-Ref-To-Java e.arg> :: e.a (e.j-arg),
481      e.rest (e.java-args e.j-arg e.comma) (e.arrays e.a);
482  } :: e.args (e.java-args) (e.arrays),
483  e.args : /*empty*/ =
484  e.arrays (e.java-args);
485
486Name-To-Java t.obj-name =
487  <RFP-Extract-Qualifiers t.obj-name> :: (e.qualifiers) e.name,
488  <? &Current-Namespace> :: e.namespace,
489  {
490    e.qualifiers : e.namespace e.cont = <Rfp2Java e.cont e.name>;
491    <Bind &Inputs (e.qualifiers) ()>,
492      <Rfp2Java (e.qualifiers e.name)>;
493  };
494
495Access-Mode t.name, {
496  <? &Exports> : e t.name e = 'public';
497  'private';
498};
499
500Free-Index =
501  <? &Free-Idx> : {
502    /*empty*/ = 1;
503    s.idx     = <"+" s.idx 1>;
504  } :: s.idx,
505  <Store &Free-Idx s.idx>,
506  s.idx;
507
Note: See TracBrowser for help on using the repository browser.