home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / lang / tcl / 1792 < prev    next >
Encoding:
Text File  |  1992-11-10  |  26.9 KB  |  609 lines

  1. Xref: sparky comp.lang.tcl:1792 comp.lang.perl:6936 comp.lang.scheme:2571
  2. Path: sparky!uunet!destroyer!sol.ctr.columbia.edu!news.cs.columbia.edu!mail
  3. Newsgroups: comp.lang.tcl,comp.lang.perl,comp.lang.scheme
  4. Date: Wed, 11 Nov 92 00:21:57 EST
  5. From: thayer@cs.columbia.edu (Charles Thayer)
  6. Message-ID: <9211110521.AA01343@cs.columbia.edu>
  7. Subject: Closures, Object-Oriented Equivalence, New version of Perl and TCL
  8. Lines: 599
  9.  
  10. [Back to the discussion of making TCL object-oriented...]
  11.  
  12. david@twg.com to comp.lang.TCL:
  13.         dh> So, thinks I, why not create a way for multiple
  14.         dh> interpreters to be active each of which thinking it owns
  15.         dh> `.' ...
  16.         dh> Since then I've realized this same stuff can be used to
  17.         dh> create modules with a hidden implementation and public
  18.         dh> interface.  It depends on using a separate interpretor to
  19.         dh> hold the implementation, and puts tiny procedures into
  20.         dh> each interpretor which wants to import the public
  21.         dh> interface.
  22.  
  23. thayer@cs.columbia.edu to comp.lang.TCL,comp.OBJECT:
  24.     me> You could implement the rest of an object oriented system by using
  25.     me> interpreters as objects once you've built the glue to talk
  26.     me> to all of them.
  27.  
  28. [continuing with my thought...]  This applies to almost all languages.
  29. That is to say that if you can create a new instance of the current
  30. language execution (or environment) you have a metaphor for an object.
  31. In Perl (or ADA :) this would be supported with `package'.  In Scheme
  32. it is a built-in concept.  [and I haven't even mentioned dictionaries
  33. in forth or postscript.]  Having a new interpretOR that acts like a
  34. normal run of the system is just like providing Perl's `package'
  35. mechanism.  In fact, David Herron says at the top of his source for
  36. the multiple-interpretOR: "An attempt at providing a `package' concept
  37. in TCL".
  38.  
  39. Grady Booch [Object-Oriented Design with Applications] describes an
  40. object as having state, behavior, and identity.  By creating an
  41. individual TCL-interpretOR, you set aside a symbol table for holding
  42. that object's state (eg. its variables.)  You also can create proc's
  43. (procedures and subroutines) that can act upon that local state to
  44. define that object's behavior.  And lastly, you have given that object
  45. identity, by naming its TCL-interpretOR, and this identity can allow
  46. you to uniquely access it later.
  47.  
  48. This however, only gives you an object, or more precisely a data
  49. abstraction that includes local state and methods.  It doesn't give one
  50. an object-oriented system.
  51.  
  52. Grady Booch describes object-oriented as having objects, classes, and
  53. inheritance.  In order to extend the simple `package' model of objects
  54. to form an object-oriented system, you'd want a way to distinguish
  55. classes of objects (eg. a class state and interface that provide
  56. functions on the class itself, such as new) and a way to inherit
  57. between classes.  To support this through a `package' mechanism it is
  58. important to be able to chain the packaged environments to control the
  59. closure of an object.
  60.  
  61. For example, in Scheme, a 'define' saves the current environment and 
  62. leaves the ability to reach the enclosing (dynamic) environment:
  63.  
  64. ;; code from Scheme and the Art of Programming
  65. (define (adder x) (lambda (y) (+ x y)))
  66. (define add8 (adder 8))
  67. (add8 3)
  68. ==> 11
  69.  
  70. Here add8 has it's y bound to 8 in the symbol table with x bound as a
  71. free symbol; Whereas adder has x and y bound as free symbols.  By saying
  72. the function is free, all I mean is that it is undefined in the
  73. environment of that particular object.  When the free symbol needs to 
  74. be resolved the enclosing environment is checked.  In this case one
  75. could view '+ as being free in adder and add8, but bound in the top-level
  76. environment (therefore not an error). 
  77.  
  78. In an object-oriented system this is a metaphor for inheritance.  An
  79. enclosing environment can create a new sub-environment that could be
  80. said to inherit the enclosing environment's state and behavior:
  81.  
  82. (begin
  83.   (define (echo h . t)
  84.     (if h (begin (display h) (echo t)) (newline)))
  85.   (echo "Running")
  86.   (define (ClassA)
  87.     (define (p) (echo "class a"))
  88.     (p)
  89.     (define (ClassB)
  90.       (p))
  91.     (define (ClassC)
  92.       (define (p) (echo "class c"))
  93.       (p))
  94.     
  95.     (ClassB)
  96.     (ClassC))
  97.   (ClassA))
  98. Running
  99. class a
  100. class a
  101. class c
  102. ;No value
  103.  
  104. Here classB inherits from classA.  And classC inherits from classA,
  105. but creates a new definition for p.  [Unfortunately, this simple
  106. example is a bit contrived to avoid fun macros and evals.  Besides,
  107. plenty of people have already written object systems in scheme :) ]
  108.  
  109. Likewise, perl has packages that have their own individuals stabs,
  110. (aka symbol tables.)  However these don't nest (well).
  111.  
  112. #!/bin/perl
  113. package main;
  114.   @package=('main');
  115.   sub moo { print "main'moo\n"; }
  116.   &main'msg(moo);
  117.  
  118. package A; @package=('A', 'main'); # just pretend this is inheritance :)
  119.   &main'msg(moo);
  120.  
  121. package B; @package=('B', 'main');
  122.   sub moo { print "B'moo\n"; }
  123.   &main'msg(moo);
  124.  
  125. [But since these environments don't nest, I kinda went and changed the 
  126. usual calling semantics to a message based one]
  127.  
  128. sub msg {
  129.     local($sub,@args)=@_;
  130.     local($package,$filename,$line)=caller;
  131.     local(@search)=eval "@$package" . "'package";
  132.     local($context);
  133.     while($context=shift @search) {
  134.     eval "&$context" . "'$sub(@args)";
  135.     return if (!$@);
  136.     }
  137. }
  138.  
  139. As one can quickly tell, it takes some doing before scheme or perl
  140. would nest their environments in a way that particularly supports
  141. inheritance.  In David Herron's interpretOR the problem of extending
  142. the system to be object-oriented is identical to the one in perl, in
  143. that environments are named at the global level.  One solution, hinted
  144. at in the above perl code, is to have an environment to manage all
  145. other environments (eg main and msg, tcl and interp.)  But this
  146. quickly becomes tiresome to do by hand, and begs for a built-in
  147. system.
  148.  
  149. As it stands, tcl is more well-behaved that Perl, but slightly less
  150. than scheme.  Here is the same program (yet again) in tcl.  You should
  151. note that variables nest in a very purposeful manner.
  152.  
  153. [thayer:0] BashER> tcl
  154. tcl>cat object.tcl
  155. #!/usr/local/bin/tcl
  156.  
  157. proc classA {} {
  158.   set str a
  159.   proc p {} { upvar str s; echo classA $s }
  160.   p
  161.   proc classB {} {
  162.     uplevel p
  163.   }
  164.   proc classC {} {
  165.     eval set tmp { [info body p] }
  166.     proc p {} { echo classC }
  167.     p
  168.     eval { proc p {} } { $tmp }
  169.   }
  170.   classB
  171.   classC
  172.   p
  173. }
  174. classA
  175.  
  176. tcl>source object.tcl
  177. classA a
  178. classA a
  179. classC
  180. classA a
  181.  
  182. Oddly, tcl gives you full access to enclosing evironments with upvar/uplevel,
  183. but is more prejudiced about making all procs global.  However,
  184. because of the thoughtful design of tcl, I can just shove aside the p
  185. proc temporarily to emulate the desired behavior.  Tcl could also be
  186. used to do as perl does, except you'd want to save procs as strings
  187. (another cumbersome system.)
  188.  
  189. David Herron's interpretOR (from my limited knowledge of its current
  190. state) would be more nicely behaved and might look like:
  191.  
  192. interp new classA
  193. interp new classB
  194. interp new classC
  195. interp eval classA {
  196.   set str a
  197.   proc p {} { upvar str s; echo [interp whoami] $s }
  198. }
  199. interp eval classB {
  200.   proc p {} { interp eval classA { p } }
  201. }
  202. interp eval classC {
  203.   proc p {} { echo [interp whoami] }
  204. }
  205. interp eval classA { p }
  206. interp eval classB { p }
  207. interp eval classC { p }
  208.  
  209. Here his closures handle partitioning of procs in a much better way
  210. than writing a messaging system, in a way that is more compatible with
  211. existing code.  However, one still yearns for a real object-system.
  212.  
  213. thayer@cs.columbia.edu to comp.lang.TCL,comp.OBJECT:
  214.     me> This is very interesting.  It would appear that you've got
  215.     me> yourself a simple closure mechanism.  And it has been said
  216.     me> that "Objects are a poor-man's closures."
  217.  
  218. pdc@dcs.ed.ac.uk to comp.OBJECT:
  219.     pc> I think this is an excellent and thought-provoking analogy.
  220.  
  221. I found it to be interesting too.  It's a proverb attributed to Norman
  222. Adams, which I read in a recent article in "AI Expert" by Kenneth Dickey,
  223. called "Scheming with Objects" [kend@data.rain.com].
  224.  
  225. throopw@sheol.UUCP to comp.OBJECT:
  226.     tw> The *interesting* relationship is that the
  227.     tw> essentially-syntactic sucrose making up the object(while)
  228.     tw> captures an interesting subcase of the closure(goto), which
  229.     tw> aids software developers in reasoning about a program's
  230.     tw> behavior.
  231.  
  232. Absolutely. Which is why one would rather have objects than closures if
  233. the language syntax can't be changed by the user.  However, it seems
  234. that there is almost never a reason to not provide both.
  235.  
  236. Yet this begs the the two questions 
  237.  
  238. (a) "what is the exact definition of a closure in a language?" so that
  239. we can know how to provide them.  I can tell you about closures in
  240. mathematical systems, or explain why certain movies have good closure,
  241. or point to lambda in some dialect of lisp and say closure, but I
  242. don't know of any good discussions about them in milieu of programming
  243. language construction --I imagine this is my own fault since I am more
  244. interested in objects.  It seems to me that the closest thing to a
  245. formal discussion of the operations on closures in a programming
  246. languages is object-oriented-design  8-?
  247.  
  248. (b) "what is the exact definition of an object oriented system?" so
  249. that we can know how to build one.  I can easily say "take objects,
  250. group them by class, and add inheritance" but so many issues exist
  251. about what language features make a system usuable for a programmer
  252. that any one implementation is doomed to exclude many such features.
  253. How should one take a system supporting closures and build a usable
  254. object system?
  255.  
  256. In fact, some would undoubtedly say that closures themselves are a
  257. subset of continuations anyway (you know who you are :) and before we
  258. know it, we are back to working with turing machines and electrons :(
  259.  
  260. What I would seek out of all this is the simplest most straight-
  261. forward way to provide an object-oriented system (maybe BOB is the
  262. answer --Doctor Dobbs.)  I see TCL or SIOD as lightweight enough to
  263. provide object-oriented systems to other programming languages such as
  264. Perl.  The idea being that a very efficient tiny object-system in tcl
  265. or siod, with the right hooks in the parent language, could function
  266. to make the parent language object-oriented (where wanted).
  267.  
  268. Objective-C did a good job of extending C in a straight-forward
  269. manner.  C++ did a good job of extending C in a not-so
  270. straight-forward, but efficient, manner.  I seek something that could
  271. be used to extend all languages that don't directly generate
  272. executable code, and that could be used as callable libraries in those
  273. that do.  Something that could be embedded in everything from awk
  274. to common lisp, cheaply.
  275.  
  276. My motivation/interest in this is a bit bizarre.  I would like to see
  277. tcl in almost everything as the new meta-tool.  Under Unix, pipelines,
  278. regexps, and tcp sockets have done a lot for allowing free and liberal
  279. tooling.  An open-tcl-interface on applications and toolkits could
  280. provide a new realm of intra-application communication and floating
  281. toolkits.  For a description of what I mean see the end of this post.
  282. [or search for the string "intra-application"]
  283.  
  284. bevan@cs.man.ac.uk to comp.OBJECT:
  285.     bv> You could always use a language which has closure(goto) and
  286.     bv> lets you the _user_ add the syntax necessary to represent
  287.     bv> object(while) when and if they want it.  One example of
  288.     bv> this would be Scheme using its (hygenic) macro system.
  289.  
  290. Absolutely.  [it is hygenic isn't it..never thought of it that way]
  291. However, I often find myself (whether the language is scheme, perl, or
  292. tcl) eval'ing something for the third or fourth time, and saying to
  293. myself "enough's enough."  Scheme is good language for writing other
  294. programming systems such as Prolog, LOOP, Ski, expert shells.  [I
  295. don't know anything about LOOP or Ski, but Stephen Bevan wrote these
  296. in scheme.]  Other languages such as Perl or Tcl, however, don't
  297. provide such facilities in the language.  To change the syntax you
  298. have to change the language. (roughly speaking.)
  299.  
  300. Besides, who wants to sit down at common lisp and write an
  301. object-system when there is already CLOS.  Who wants to add networking
  302. code to TCL when there is Perl.  Who wants to write for X using the
  303. Athena Widget Set when there is WAFE.  Likewise, nobody wants to write
  304. while from a goto, when they sit down to work in a language.
  305.  
  306. throopw@sheol.UUCP to comp.OBJECT:
  307.     tw> But it has been discussed many times on comp.object, so if
  308.     tw> I'm overlooking a FAQ, or pummeling a deceased equine,
  309.     tw> please treat me gently.
  310.  
  311. ``I would call you a sado-masochistic-equestrian-necrofeliac, but 
  312. that would be beating a dead horse''  --anonymous
  313.  
  314. I see it's 3:36am here in New York, so I'm going to get back coding.
  315. Here's a small present for those that read all the way to this point:
  316.  
  317. #!/bin/perl
  318.  
  319. # Prints a profile of most used words.  The actual work in progress
  320. # is yet another mail pre-sifter.
  321.  
  322. $garbage='[ \t\n,.<>\[\]{}!@&^|]';
  323. while(<>) {
  324.     /$garbage*(.*)/; $_ = $1;
  325.     @wordlist = split(/$garbage/);
  326.     $wc{$word}++ while($word = shift wordlist);
  327. }
  328. unshift(@prof, "$wc{$word}:$word") while($word = shift @keys);
  329. sub bynumber { $b <=> $a; }
  330. @nwc = sort bynumber @prof;
  331. print "$word\n" while ($word = shift @nwc);
  332.  
  333.  
  334. /charles 
  335. ==============================================================================
  336. Charles Thayer, Columbia University, Dept. CS, Tech-staff... my words only.
  337. ==============================================================================
  338. PS. Gee, so much writing and only the tip of the iceburg, drat.
  339.  
  340. PPS. Please forgive my cross posting.  This has relevance to the various
  341. requests for an "Object-Oriented Perl" [c.l.perl], the discussion of
  342. "Multiple Interpreters in TCL / Spawning" [c.l.tcl], "objects and
  343. closures" [c.object], and more scheme code than I intended
  344. [c.l.scheme].
  345.  
  346. PPPS. Here is what I meant about intra-application communication and 
  347. open-ended toolkits:
  348.  
  349. Imagine the following scenario where I am writing an nfs-client
  350. filesystem that will allow users to safely have mail delivered to
  351. their home directory.  Here's what I would be running:
  352. ------------------------------------------------------------
  353. X
  354. tvtwm or your favorite window manager
  355. editor on my source
  356. debugger on the programmer
  357. xterm to recompile and test the program
  358. latex to format the documentation
  359. xdvi to view the documentation in a pretty window
  360. editor on the documentation
  361. xclock to point out how behind I am
  362. mega-biff that tells me if I have mail or if any new netnews has come in
  363. trn to look for info on nfs-bugs
  364. archie to find other example nfs-clients
  365. ftp to grab example source
  366. xnetload reports the load on machines around the network
  367. xcpustate tells me that I need twice as much memory
  368. xwafeping gives me the thumbs down if a machine goes off the net
  369. xwafenetmate gives the number of users on machines around the network
  370. editor to read my mail
  371. xterm on another host to test the nfs-client remotely
  372. vmstat in an xterm to tells that I am about to blow my lid
  373. ------------------------------------------------------------
  374.  
  375. Now imagine that these all had dinky little tcl front-ends that spoke
  376. some IPC or TCP.  Imagine these tools written in tcl with procs to 
  377. interface to all the underlying utility:
  378.  
  379. ============================================================
  380. systat - daemon that has interface to load, vmstat, users and all the
  381. fun system things like disk writes and reads, each as a tcl proc.
  382.  
  383. term-manager - lets you control multiple terminals as a group of windows
  384. on as many displays as you like.  If one terminal overlaps another it 
  385. could automatically move to fit in a programmed way.
  386.  
  387. editor - lets you bring up as many windows and buffers as you, with
  388. multiple font support, and cross talking between buffers. (just like
  389. lucid emacs :)
  390.  
  391. ftp-er - supports a little progress window to many ftp sites, and
  392. remembers what ftp sites you've been to and what software you got, and
  393. where you put it.
  394.  
  395. rfc-822 - a bunch of functions to process rfc-compliant mail
  396.  
  397. trn-manager - like trn but now you can apply brutal regexps to kill
  398. off threads, and has nice bookmarking so that you can save messages
  399. more easily.
  400.  
  401. xdvi - same as it ever was but reprogrammable, so now you have a that
  402. print button you always wanted.
  403.  
  404. gdb-engine - follows a process here or there.
  405.  
  406. tcl-latex - same as tex or latex, but tells you where the current
  407. token is in the parser.
  408. ============================================================
  409.  
  410. Okay, now imagine that all of these work together with a send command.
  411. The send command allows processA to execute TCL-code in processB.
  412.  
  413. c-mode in my editor brings up a bunch of buttons on the top of my
  414. buffer.  I hit the one marked compile and another window comes into
  415. the foreground with make running on my file (the editor has just
  416. executed "send buffer *compile* restart".)  The compile fails and the
  417. whole compile screen turns red, and my source buffer now highlights
  418. a miscreant line in my makefile (the editor has just executed "send
  419. buffer-set *source* error on line 234 Makefile".)  
  420.  
  421. I fix the Makefile and the compile works.  Now I hit the run button on
  422. the top of my c-code buffer, and gdb comes to the foreground running
  423. my program and highlighting the line currently being executed in my
  424. c-code.  The run of the program is actually being displayed in a window
  425. run by the term-manager, and simultaneous on a read-only window on 
  426. a friends xterminal.  The friend is a project partner, for whom I 
  427. granted access to certain xwindows.
  428.  
  429. A piece of mail arrives for my account and a window pops up.  This
  430. is because I have told my mega-biff to pipe my incoming mail through
  431. the rfc-822 server then check for certain fields.  I "set from-match
  432. '*[Uu]rgent*'" in my mega-biff.rc file so that the window would pop
  433. up and beep a few times.  Incidentally, I have also put the following
  434. in my mega-biff.rc file:
  435.  
  436. proc pop-up {
  437.   send loudly editor pop-to-buffer *in-mail* from [extract msg $last msg]
  438.   send editor send buffer *in-mail* { beep; beep; display-time }
  439. }
  440.  
  441. The mega-biff doesn't know how to pop-up incoming mail, but I have
  442. taught it to send it to my editor if it noticed an interesting from
  443. line.
  444.  
  445. Interestingly, although there are three or four users on the machine,
  446. there is only one rfc-822 running.  Every new connection is assigned
  447. it's own "interp new rcf-822.$port.$user.$host" so that multiple users
  448. share the same code, but not data.
  449.  
  450. I read the mail, it is from my project partner who says "joe has heard
  451. of a package called hlfsd that implements an nfs-client."  So I go to
  452. my archie screen, where I am foolishly executing "prog nfs", and hit
  453. the button "new interp".  This brings up a new archie client (also
  454. David Herron's interpretOR) where I type "prog { hlfsd* } on { prep
  455. cs.columbia barkley.berk } do { pop-found-list }".  As you can imagine
  456. "pop-found-list" sends the results of a search to my editor, or if I
  457. have no editor running, I have programmed it to just send me mail.
  458.  
  459. This goes on for hours...of course. 
  460.  
  461. Every now and then my mega-biff notices a new news posting with the
  462. word closure in the subject line and pops up (via the term-manager) a
  463. terminal session running trn, and doubles the size of my xclock so
  464. that I don't loose track of time.
  465.  
  466. Every now and again my xdvi window pops up, when my friend sends 
  467. his latex output to both of our xdvi's to show me a new page of
  468. our documentation.
  469.  
  470. I get bored of working on the code at hand, so I write a simple
  471. network monitor shell script.  It allows me to add or delete hosts to
  472. watch and it brings up an xwafeclock inside itself when a host goes
  473. down to point out the time of death, otherwise it queries the remote
  474. systat "send host moose.cs.columbia.edu tcl-agent systat load-5;
  475. load-10; load-15" and draws a graph of load with the results.
  476.  
  477. ETC...Etc...etc...
  478.  
  479. PS.  I would want to write the "backends" to these things in perl if perl
  480. had a good open-interface to things like tcl.
  481.  
  482. For those who read this far here is another small perl present, and
  483. another work in progress.  It generates tvtwm menus from dns and yp
  484. information.
  485.  
  486. begin 444 tvtwmrc.pl
  487. M'YV0(T*\$)/&S0LX9>2P4:!@!(@S9=PD#$.G#(@V>4#0L4/G3ALY8T"$J4/G
  488. M31N*:<:$8<,F#PL0=>:4F0."B),I+_/ >?FB#)TQ+\BDF4/'3!HV,T6Z(=-0
  489. M(QJ+;-*LL5CR8<2)%4$4K"AG)IV"9RY&C"F2I$F4*EGF<<%P#)HW<%"0('.V
  490. M8 \P PL&K>O&39@V9<"DV*$ ;D04-G&*>$L41 LVCNF 0%/0S!L0<_F"X",B
  491. MQ68^"D"(!B'4HH@A;^JP(>/FA&2(DAE+KGS9LAS,=$\6%$'8L!L43ZI082'"
  492. MAXN-'3^.<3&R)$2)<BB6(=.9L$RD8^@ %SY8 0D^/6(0;DKE*6F*8<2$D0GB
  493. MC9G);QK3EG/RZQLW6FF*J7-4,ID\?K61TDHM@6"&'":1YL8<"MQ!&5(H\)"8
  494. M#Y[M$=IH;L%%V&@@L/%&6G*Q(1L+)%#FAF4DSI'''"3&ET(/<\ 1E78O@/ "
  495. MB5]TQZ&'()(PAVPOQC@C"B]PX<*-)(@8'QTZCC;7@E^H.,<>/LK61P\^KKBA
  496. MDZS-\45\5/ZXY)4DQ$=8'PJ,X2%[B8WGD!1EA$&&4Q85! =)2LVY54)P="59
  497. MC&6,D<9*((QATDE+,>C@465$2$005 1!(0@6<NC0% @)2F@8V:5Q7WX:A3$5
  498. M?FF\%T:'!5DD1AEG%$13&$N!$!$9--V1!AUH@ #$A:(Y="I""A5Z**QZTF0;
  499. M8'KBAZM%EK'TAJUNA'5'&'GHP"L(#@%A:!N(SAF&'&?$(!*X,H#@PKGCGN'$
  500. MKI:"8,*VW:*0;@PO?7N&#"^=ZT*]X#H!0I.BE0H"D5X @8(+*Z0 ! DO5*A 
  501. M CRN)!>\Q+( A+US!"GCK43:2&(,W4'\H<0DC$&4'&"]*(())0^[E+R\/1PQ
  502. M&W+1T08<05)FAF07@SL'80F4?#)8/8@@-!TH1XN9S7#$G,"B$)+ -(PZ\XQQ
  503. MA9B9C#311FN=]!DO27TS;R"@&;377!_]];\[<.&&TV7803+:T7K&!Q\@3"L'
  504. M?B((4<41.F0]=+0Q<]B'K&RP9V$"#B5A*JH2@>K&&Y*=2G&LMX(:Z%O3/=SG
  505. M5IA]L:5H:*)9!AZ9P^ F"$V(FM2I@+E1AZQN()V1;2#(44=?8"D% AY<M:' 
  506. M''6(\7OPE%[KT++IUA$[':]VE3NKIQO[QFTC@B!E16UHI%,9]<8:G_<(73NS
  507. M7/6Y]47V)*2/1I0KDNC^EQGW (3H38WV>>T@B. 0$V]XPQIZASL>M(\BZAO1
  508. M 7_R/BG)#X'OBX\/W%:XT9P/"%-949"N)YD,S@$%)>@2_0#6H9'1K$1+(B'4
  509. M+"(7V5"M5-K!8!DTZ+ $" P%1I.-"'K@!Z/-3X<UW)$)Y>(B+(D03"@D2A^ 
  510. MQJ$;&BT^.^SA M4'Q1J*K$=2>M&3O"0E*ED):#9\#PZS-(<H^A""\"NC%3ED
  511. M N E1$!^.2&0P'BX,B3.(A8:00(2P*']2<9_VEL1:=+ &M=<!((&NAX(#*C 
  512. M^*1H11-\&QT?9CC$*:XA>_1C_QPR/J$44C+N2^1M&+FD%LTADDXSW,/J>,?D
  513. MZ;&/2?NC0V0SR$\>DH&B7&02Z8!*H*%)E1P2CP+0-+SB@2 /R*N4!8=(@C,@
  514. MJ XXLQ_^'**_6&Z23@]Y)AQ U4QM4G!T)>Q15(CR(C#H))3=3,TV)4('9ZH3
  515. M#(2AIF@T"<AQSH8F21H*';YIOB$"P9X;E(-VA,2Q%VP!!%S8IQNZL (D ;0[
  516. M\@0!/1UB3U#]4Y_\%&*/YGBM%0YLER_<&0HN2LX:MC%X!2$91X$Y&F$2DWC&
  517. MRX-*DMG/'K'3G=!\T?W .5%LXG2;0\',3;TIR6OY!@59@ )Q=#)3H?KDIYPA
  518. MX04!"LX51BBID]I#H=X"AQW 9$%5&ZD]<328LEV+I'2 $0=U9<]XPA)T]=2G
  519. M1>WY30[55*4IK.J#6 C2'\%0K/I,00W/5Z44PFAC-#(2DCB:@).^,:4G%!,Y
  520. MP?G+EIZ)(3 =)%%.0I2$)*^)8FS!;430DY\$19]&08H:DY< WPA%#HA)PA2H
  521. M8(0D,*$(BBDM4(1"E-3.I#HR\^=K =J#KLCIM;&=;6UO.X60X0X%<^#@2(<;
  522. MV" N$XM .NR0BG2DD&F49&:( VNT*%G)N  $)W#!"<R%&[XP<30W)$%X62.K
  523. M.(3.BHZE#V3E4E[OCL9L9E-3?*:3!M@20;:TM2UN0R;,2MI1<:HK'6:-Z4;]
  524. MQO&SU\4K.:7)4VN*@ LY7!*($QH"$%>X>RV8 V1B (,6.V8.QFL!?G;I&"I@
  525. MAI8M,!X-'','$.RX!6W0#QOJ8)$5X*D%%E'(&UHU8]FX(#.ZP8\)1ES48%ZV
  526. MF,8CGAN^$+O9*5,TA)72%V37!IWB[ZW\$T&7$2H"DVEO=Y@1,YFIO >W@7@(
  527. M4P#!%';7 AJ\@(QC=MZ(BW*<6R&E@J+);QMPZ (5B. E(MBS&_K\9SD[[]']
  528. MJX(;TH 'X*+YCWVP<U%?:LP E8'+8\$PF)DY/U.;N<-P73.(W:QES+3Z+V6@
  529. MLYU/DV=)VQJ-IAZT&0I-AT.#4]$X],(6IO@^4W>AT9B.-)_]#&U(:YK3GJXF
  530. M7$/M!GX2\PM?*((3B !N\E"&)D%MSEF^DI8"/0<KG7,(:DZ4AC/4(3KVP8]O
  531. M<XD<C["E*06YU:"BH@>4W(=!J/'0;18GA.N1(2$)5Z0(Q, &3JU!! ]+@J'<
  532. MT#J_0$0.2*@W&J)R!C3\D>)$%@&E^H<'.,B)1Q?O7U>H8U9B-N$^'T(#@@##
  533. MVH;+X>%RB/AHA5#Q,5Q\F QQPANH8&@\[M$A=&G-G][2XZ\4NPSJD8/U;K,L
  534. M]D"++G=@4 )$@ </R0GC8\>#@(V.=K(3Q QF:#L>9OC;AY$=47(?PYV((IVV
  535. MEP0.#>\TXWZ'J!/4JB!@MSL>9.(3G==![NPT.W7L_O YK.'O&.]# I+^AI"7
  536. MG.0F9^UI#OZ&0P]^X]%%2MX0_ZQ<IH8.=Y+,?5JB>,;C2G=YA[G<)0]YG_!>
  537. M\70O(](5H/'[=#P,'R?"?>@P!:J+7NVZ5_SOTQ[Y-YP=^'FH>]K?'G?%NYP,
  538. MT1\[%):4!#HHO2*9WSSQ-W[\CQMA^?VS 1Y8+(+!3^$D+-'*Q@_I\82PA>E7
  539. M]WYI)G_T9W_X!QE6IWI9-P=L$01F 2<5]Q5V4 9P,@=IH =E,'A1P!]&-ST6
  540. MB(%Y\Q3X$09R<Q3I@11L(07$8A)04'1E\#Q/!P),X!/8]'6MARC(YUDRPBD6
  541. M$09PL#$SY2D+PA;%MVEFD ="D >:UCH_"!:#%Q-481XI\2EB\ 9X0!C-]RQ%
  542. MV'X)$8.\M8,9P3Q3B!\;1P=AD"IRL'[&!RLY* ='4 8FX1-RD!$BP&(P@ <R
  543. MT&(M  ,K  /UYQ .DA!ULG\X^'$/\08ST1!7\"UP, 3W%EUR$(-M\ 836"B/
  544. MJ$A588,]%@8[XUD/-X:ED@=@H0!$4 9F,!)L0 =&L#N=\BG#MBIE  <*, 5Q
  545. M0&1E@($ B!0Q*"8"I1%-!P(+J !0 "O0\89Q:#O]LX<M8(<89P4%1@=UL!*E
  546. M:'E_US\Q@ <T@''#V!<),05FF!4B,#GTL1(8EX5WX(P"%8ULX 2XQB#>F!)K
  547. MD!&+(P)4< 5-  )%R#IL^'&Y]R%'1TP.L1]T4!(+PA !21($"0(]  (>E "!
  548. M4X:G(QF!8P:LF&\*( 0(>1_BLI .F3L!1 <=.6QK%FDS88$'AW$8.9#W42X]
  549. MT)$(0CDAZ0(C204><06L%W8HF9%N, ,*Z9(?&9,C:9-+T7JKZ :MN" 8=Y$Z
  550. MR9(=.89MX$P@,)$NX"%WD!!*J9([V9.!XY10*944:93YUC\/)UIG*!,R]@8M
  551. M8!EC$!-)F9($N9$@T)0;%Y.@>(1729 \V9);.9=2.8D3R!!NJ9$*R2&B$3@)
  552. M:!%1:2 N$!U#84?/8I6!Z08L29B)>9B%J9A4"9DZF9>4:9B_F)@B28EE )@Z
  553. M"9<TP2&!HXF7.6R,*1-WN9*#>9JCD9HWN9HRF6HB()1@!P)%>93"%YF<*9N7
  554. MJ9J@Z0)UF0>DB96FV9D>23FV.9)-,!1CD)-8.9G">9DO*1G%.9))<"+74Q]"
  555. M2)UX&9O,F9W/B9M3L"+<DY0BH'QW\#8)H)<BP1(Q.0=C@" L 79NH  B4 5-
  556. M$Y\=22#U>9^E-V2R* )($(?U)Y\"*I7VB9]* A@,(0)&$ ,+&J#TZ: $FG\B
  557. MT(=]B'$4*@,7&C@-JI@/6J#]XZ$6RI]&, ,C.I]L,* 0FJ)\**(LFHT 2J(9
  558. M:J(;"AD=RH<NRJ(U\*(E.FPGRJ$>FHTL:@-$NJ-&VJ,TN@)#RJ(WT*0QJJ$S
  559. M^J,KP*0LB@-6*J,HJJ55:I!B(3O:$R@6J0"]&98B,):M609GF98?PI8*\&6*
  560. M^8D;%XK7PIIE.9H1-6QJ&1/#MZ9"*'-]*F-RNI;"9Z=\VIA[Z@*!RB#$-))3
  561. M4))"N*BA(0(W]P:5.@<FB90),&R'F:EXIF=PE@10@ 7U)Y*X26MP5@-^2*J]
  562. M!F<V, -^&*JW::9M1A.U5JNQVC^E*FFO(@;3B:LCZ:HC2*P8!ZRSNB"D88JK
  563. MFJNSLZMOAA\/UWW,:JK.6G)I$*W'RJMPQJW+RFO:2A-JL 9LX*VM"J[X<:[I
  564. M*JOE>A&3HZZZBJSR^@;C&JR[0Q-P$ =R0*_3:J_]^J_P*JS: XT VS_V2A2/
  565. M5[#["@)V@ =YH <)2ZVU%K$3FZ]YA@104$;&NJZ3 0?"EZTW1Q"J5;%N%F2>
  566. MJK$@D%0R(0<3J'4H2Q,ZP;)$H$\GD! >RZKU2A.\10?C&@1C(%OU][&ZRBE!
  567. M)1LC.WH+4GIE4'\A0';(DV(KUF(PX!CX,6^I9Q$M8&-:Z[0O%F-BT&,_%F3 
  568. M.&1<>V2@&!(M, 3N@G$.08]E<'D(LFDF [52^T8O5K4N)F,@0 5SBS3WD1(T
  569. MT;5_&[AU2[AAZQ@ZYAAFBW)<2[:.80;XD0/S9P/J01-&)ADM(!DF,*XG!@(R
  570. M@*-1&[I4"P)V>+6&2P)(\ 2S];:9&KHU4*4)4+I3JV*H:[4UAAFM^[J?VQ0B
  571. M( 5/\ 0V-@5(4 1,P 1X:[JXF[I8"P+"2[P+LP>]2P6'8[C12P736[W7"V.,
  572. MZV..*V1$QF/@FY:5>[F9.[G20AE9D6-A07$6YQC,,CLM,#L(4A6_&[=&$ 2S
  573. M)03#2P7+>[M\>[4D0+VN:[V[N[_]^[_;>\#=*[;E^[AH2[X_1KD@8+DQ@+GK
  574. MH;XA>"M<*P;O6W1K(+\&0K_V2SF7H5LO<(I$487.^;O$! 1:AFIF"JN[(L.[
  575. M0\.SXZLW;&HZ+!+$VL.X]L/7*L2 \</<:L2GMF;NJL0_W :3X\1K-K!2G&H,
  576. M6\5FBK%ZL"L*\*TABZGDRK$[2VQ(H0! $+HB &W]P[$MD -6BS JUY^;UFF[
  577. M,JD@J[)@7*HERR@@D*!$,<:C"@3(I+>["F2>6D9US!!>7+-URI^EZK()$;. 
  578. MW'1F+%/201_]HQ,O*\DBD,A=#+(_BW$60JXW2Q0Y*[.X&L@_RUE<X<DCB;0T
  579. MH;2B[,AU, 8JT<=+,LE71ZJ[PVE&$,!Z>[K.Z[=#4 5.D 188 2[6\S'G,R+
  580. MFV,1++Z1"[Z;R\%B@"#O2<)*QF26.,?O\;L*V\MX$ 3 C,G"K+M^NY9S?"J&
  581. MJ\Z<QL[>"\UE*\T4+!K5+%IV$+X=W+Y)YB'<[,YX<"K@W&;B+ 3EC&+-B\YD
  582. M*,XQ9F, '6/QW+B&?+;CVP*2"P+W#+/ZO"C\G#O^7!#=S&G&,]  700'O;>Y
  583. MV[<+/<=<Z]#BS+41'<T4/<T[AM%'IM$3S=%<V\]+!M( ;1$#+02ZLR"VPG:U
  584. MF[?FG- J'=)X,"?M+,Y.'=/S/-/U;-.<B]-FJ]/:_-$KS6ES$M2P4G#=>M3,
  585. M.\#/JQYN(-:[*P2PH@5G^,P2+<$5?=$9G<\YS;X[[=$]C1]HK=8PK,@@6VMA
  586. M\!BS3*X&&P0MH+RI3,EGC#PBH&R#S0;/YFC](VEJ+,?8YLJ!#6=MT (4V\B&
  587. M_;!-T ):$*V!C,;*UMEZ,-EQ;-F4C=ET/'Q>+,N@7:I^##VF3<F92A=U< 85
  588. MM[)D+< IK;K6FAJ^O1Z%:V.\?=R>"M<R#;GU7-<;C==;O=>D8=R_31,#'16K
  589. M(E!Y<-+GO-3<G1!TD!&&.][>[=Q3#=T63<TW;==93=U(IM?<C-[E#;O]TP:J
  590. MT=US"-Y*3=P7L=\),8>[J]]LP-_F+=7ZS-Z2*]UW[<'5S<T&CN#XW69/012R
  591. M [3!'<S__;QNX149OKL?CN%'IN 3S>#N?=7P72ORS=/_?.%T$.(#+11V,!3A
  592. MN>%);=9^2^,V_BF&R^.?JMX+/L'MO6,.'M\0/M_;#-) 7J@#C09U0"OWX=\Z
  593. MCA]0+N7X8;A7'EU9;N)R3=-6[1A8S>))[N(@O>6?,M"V<7%[9+L<7N6B-,*&
  594. MN^9"?N)$+KGF&^;X/-UE3M\@3>=__<FZJIM$69&76MB$WF.$>I*+O<O!:XI=
  595. M\2,@$ 3)6[2L">DS@0;\"2<'DNF6[@+0TA6=_B/\N8W0\>DNQXUIJ*FB6;3&
  596. M*IJ;/A,7^+1[=.D?.)K!VZ>NWJBN*0( 5)7_ND>XFIFK7H2A^.G'R9^E:.Q'
  597. M^.EX.KAV2:%S2A.?DNC1&JDL.NWM@1]2\)&?OCO8+@):$$!ML.LNH ?DSJ*J
  598. MP0;C;A*?3I$L@>XF$>M\)U"?'NEF*%#\V0+\WN_^_N_1.CD'N@2VI=BU[@*5
  599. M)[C(*0)14 5) ,#"/FRU>"NRC9[J^8*%G9Z=5>X'/ZJ:ZCP41^MD#7.PJZF<
  600. M8B)087W4T>9D)WF. 4UD(!T@4 ,OEA86P9._*P).X!-W<#TCS'LLCP?5)R<E
  601. M/P104 5Z]HTB7[IZ%Q-*[Q@0<8P$O@(QL(PP("XY#P4)808W!Y]D#2QF,(E2
  602. M!J)8, 8G\9]!;_8^6/)EKWMI3_*!#IW26=C1:9]V5'$2D1H>V^AE+ )%D'U[
  603. M3];!!_5P"!C(& .V.G\MM@*V"@/+6/*EN!]GP(]!3P9B@ >$+_4940,T8+DX
  604. M< ,VX*&J:\$8/ .9F_-#L!)K&8'74[1,K_HECP2GD_IL4*Q'_11J!_M9OR2W
  605. MXOID!P>\S[ES8-?Q;,$$>+5QCYO=>2P&]S:@O?S?V?R?[O$=IXX2E8-[7[J(
  606. 4DOF&3^"(?X=VN (T0 ..C_69IP#=
  607.  
  608. end
  609.