home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / object / 4191 < prev    next >
Encoding:
Text File  |  1992-11-10  |  27.0 KB  |  612 lines

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