Path: tut.cis.ohio-state.edu!pacific.mps.ohio-state.edu!linac!uwm.edu!cs.utexas.edu!uunet!sraco1!sakoh
From: sakoh@sraco2.us.sra.co.jp (Hiroshi &)
Newsgroups: comp.lang.perl
#Subject: Re: operl - an experimental object-oriented package for perl
Message-ID: <SAKOH.91Feb22170457@sraco2.us.sra.co.jp>
Date: 22 Feb 91 08:04:57 GMT
References: <SAKOH.91Feb21092426@sraco2.us.sra.co.jp> <123551@uunet.UU.NET>
Sender: usenet@sraco1.us.sra.CO.JP
Organization: Software Research Associates, Inc. Boulder Lab.
Lines: 451
In-reply-to: rbj@uunet.UU.NET's message of 22 Feb 91 02:41:36 GMT


in article <123551@uunet.UU.NET>
	rbj@uunet.UU.NET (Root Boy Jim) wrote:

   >>Why, pray tell, does source code contain unprintables?
   >>
   >>Like C and postscript, perl makes it possible to represent
   >>unprintables by using \ escapes. It is bad form to do otherwise.

Actually ,the formerly posted source code contains portion like : q^A ... q^A 
(where ^A represents control-A) for some reason.
I dont't think we can use q\001 ... q\001 instead.

But you are right. That nuisance should be avoided as much as possible.
Here I recode and repost my submission.
There are no unprintable characters now.

Thank you for your advice.

* I don't want to claim that we should incorporate
* OO features into perl itself.
* I've just present this package as a tiny proof of flexibility of perl
* and for fun :-)

Hiroshi Sakoh
sakoh@sra.co.jp or uunet!sraco1!sakoh

---<cut here>-----------------------------------------------
#/bin/sh
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by sraco2! on Fri Feb 22 00:58:00 MST 1991
# Contents:  bag.pl operl.pl point.pl set.pl stack.pl sample1 sample2 sample3
#	sample4 sample5 sample6
 
echo x - bag.pl
sed 's/^@//' > "bag.pl" <<'@//E*O*F bag.pl//'
#/usr/bin/perl
require 'operl.pl';

&defclass ('bag','root');
&defmethod('bag','put',      '$elements{$_[0]}++;');
&defmethod('bag','how_many', '$elements{$_[0]};');
&defmethod('bag','kinds',    'keys(%elements);');
&defmethod('bag','delete', 
	'delete $elements{$_[0]} if --$elements{$_[0]} <= 0;');
&defmethod('bag','has',      'defined($elements{$_[0]})');
&defmethod('bag','size',     'foreach $n (%elements) {$sum += $n;};$sum;');
&defmethod('bag','dump',
    'while (($key, $val) = each %elements) {print "$key = $val\n";}');

1;
@//E*O*F bag.pl//
chmod u=r,g=r,o=r bag.pl
 
echo x - operl.pl
sed 's/^@//' > "operl.pl" <<'@//E*O*F operl.pl//'
#/usr/bin/perl
#
# $Header: operl.pl,v 1.7 91/02/20 15:43:19 sakoh Locked $
# An experimental object-oriented package for perl.
#
package operl;
require 'dumpvar.pl';
#
# an object id = $root . $salt;
#
$root = 'operl_';  # object id root
$salt = 'a';       # object id salt;

#
# &defclass(class, superclass)
#
sub main'defclass {
    local($class) = shift;  # class name
    local($super) = shift;  # super class name

    if (defined($superclass{$super})) {
	$superclass{$class} = $super;
    } else {
	print "no such super class:" . $super . "\n";
    }
}

#
# &defmethod(class, method, body)
#
sub main'defmethod {
    local($class)  = shift; # class name
    local($method) = shift; # method name
    local($body)   = shift; # method body
    local($defs);
    local($result);

    if (!defined($superclass{$class})) {
        print "no such class:" . $class . "\n";
        return -1;
    }
    $methods{$class} .= "$method:";
    $defs = qq!sub $class'$method {! .
	     q!local($context) = shift; ! .
             q!eval "package $context;" . '$self = ' . "$context;"! .
             qq!. q\001! .
             $body . qq!\001;};!;
    $result = eval $defs;
    print $@ . "\n" unless $@ eq '';
    $result;
}

#
# &newobject(class)
#
sub main'newobject {
    local($class) = shift; # class name
    local($newobj);

    if (!defined($superclass{$class})) {
        print "no such class:" . $class . "\n";
        return -1;
    }

    $newobj = $root . $salt++;
    $myclass{$newobj} = $class;

    &main'send($newobj, 'init', @_); # call init with args
    return $newobj;
}

#
# &send(object, method, arg1, arg2, ...)
#
sub main'send {
    local($object) = shift; # objec
    local($method) = shift; # method name
    local($class, $result, $xyz);

    if ($main'msgtrace != 0) {
	$msglevel ++;
	warn "[$msglevel]:&send($object, $method, @_)";
    }
    if ($object !~ /^operl_/o) {
        warn "no such object:" . $object . "\n";
	$msglevel -- if $main'msgtrace != 0;
        return -1;
    }
    $class =  $myclass{$object};

    while (index($methods{$class}, "$method:") < 0) {
	if ($class eq 'root') {
	    warn "unknown message:" . $method . "\n";
	    $msglevel -- if $main'msgtrace != 0;
            return undef;
        }
        $class = $superclass{$class}; # chain to super class
    }
    $xyz = "$class'$method"; # subroutine to be invoked
    $result = do $xyz($object, @_);   # subroutine call
    print $@ . "\n" unless $@ eq '';
    if ($main'msgtrace != 0) {
	warn " ==> " . (($result eq undef) ? 'undef' : $result) . "\n";
	$msglevel --;
    }
    $result;
}

#
# &dumpclass()
#
sub main'dumpclass {
    while (($key, $val) = each %superclass) {
	print $key . " is a subclass of " . $val . "\n";
    }
}

#
# important built-in : 'root' class
#
$superclass{'root'} = 'root';     # 'root' is the super class of itself.
&main'defmethod('root', 'init', ''); # do nothing
&main'defmethod('root', 'class',
q!
    $operl'myclass{$self};
 !);
&main'defmethod('root', 'show_parents',
q!  local($class) = $operl'myclass{$self};
    while ($class ne 'root') {
	print $class . " -> ";
        $class = $operl'superclass{$class}; # chain to the super class
    }
    print "root\n";
 !);
&main'defmethod('root', 'show_self',
q!    print "class:" . $operl'myclass{$self} . "\n";
      print "methods:" . $operl'methods{$operl'myclass{$self}} . "\n";
      &main'dumpvar($self);
 !); # self dump

1;
@//E*O*F operl.pl//
chmod u=rw,g=r,o=r operl.pl
 
echo x - point.pl
sed 's/^@//' > "point.pl" <<'@//E*O*F point.pl//'
#/usr/bin/perl
require 'operl.pl';

&defclass ('point','root');
&defmethod('point','init',
    '$xx = defined($_[0]) ? $_[0] : 0; $yy = defined($_[1]) ? $_[1] : 0;');
&defmethod('point','move',
    '$xx = defined($_[0]) ? $_[0] : $xx; $yy = defined($_[1]) ? $_[1] : $yy;');
&defmethod('point','movex', '$xx = defined($_[0]) ? $_[0] : $xx;');
&defmethod('point','movey', '$yy = defined($_[0]) ? $_[0] : $yy;');
&defmethod('point','rmove',
    '$xx += defined($_[0]) ? $_[0] : 0; $yy += defined($_[1]) ? $_[1] : 0;');
&defmethod('point','rmovex', '$xx += defined($_[0]) ? $_[0] : 0;');
&defmethod('point','rmovey', '$yy += defined($_[0]) ? $_[0] : 0;');
&defmethod('point','x', '$xx;');
&defmethod('point','y', '$yy;');

1;
@//E*O*F point.pl//
chmod u=r,g=r,o=r point.pl
 
echo x - set.pl
sed 's/^@//' > "set.pl" <<'@//E*O*F set.pl//'
#/usr/bin/perl
require 'bag.pl';

&defclass ('set','bag');
&defmethod('set','put',    '$elements{$_[0]}=1;');
&defmethod('set','size',   'length(%elements);');

1;
@//E*O*F set.pl//
chmod u=r,g=r,o=r set.pl
 
echo x - stack.pl
sed 's/^@//' > "stack.pl" <<'@//E*O*F stack.pl//'
#/usr/bin/perl
require 'operl.pl';

&defclass ('stack','root');
&defmethod('stack','init','$inx = 0');
&defmethod('stack','push','$stk[$inx++] = $_[0];');
&defmethod('stack','pop',
	   'warn "warn: empty stack.\n" if ($inx <= 0);$inx -- if $inx > 0;');
&defmethod('stack','top',
	   'warn "warn: empty stack.\n" if ($inx <= 0);$stk[$inx - 1]');
&defmethod('stack','length','$inx;');
&defmethod('stack','dump','foreach $item (@stk) {print "(" . $item . ")\n";}');

1;
@//E*O*F stack.pl//
chmod u=r,g=r,o=r stack.pl
 
echo x - sample1
sed 's/^@//' > "sample1" <<'@//E*O*F sample1//'
#/usr/bin/perl
require 'operl.pl';

&defclass('hello', 'root');
&defclass('hehe', 'hello');
&defclass('fufu', 'hehe');

&dumpclass();

@//E*O*F sample1//
chmod u=rwx,g=rwx,o=rx sample1
 
echo x - sample2
sed 's/^@//' > "sample2" <<'@//E*O*F sample2//'
#/usr/bin/perl
require 'operl.pl';

# define new class 'hello' as subclass of 'root'
&defclass ('hello', 'root');

# 'init' method will be invoked on creating an object
&defmethod('hello', 'init', '$i = 0;');

# method 'add1' adds 1 to $i
&defmethod('hello', 'add1', '$i++;');

# method 'show' shows the value of $i
&defmethod('hello', 'show', 'print "-> " . $i . "\n";');

$o1 = &newobject('hello');
$o2 = &newobject('hello');

print "first  object=" . $o1 . "\n";
print "second object=" . $o2 . "\n";

print "Apply several operations on $o1\n";
&send($o1, 'add1');
&send($o1, 'show');
&send($o1, 'add1');
&send($o1, 'show');
&send($o1, 'add1');
&send($o1, 'show');
&send($o1, 'add1');
&send($o1, 'show');

print "See? There is no change in $o2\n";
&send($o2, 'show');

&dumpclass();
@//E*O*F sample2//
chmod u=rwx,g=rwx,o=rx sample2
 
echo x - sample3
sed 's/^@//' > "sample3" <<'@//E*O*F sample3//'
#/usr/bin/perl
require 'set.pl';

$set1 = &newobject('set'); # Elements can't duplicate in set class
$bag1 = &newobject('bag'); # Elements can duplicate in bag class

print "** set **\n";
&send($set1, 'put', 'banana');
&send($set1, 'put', 'apple');
&send($set1, 'put', 'orange');
&send($set1, 'put', 'orange');
&send($set1, 'put', 'orange');

print "Orange Total=" . &send($set1, 'how_many', 'orange') . "\n";
&send($set1, 'dump');
&send($set1, 'show_self');

&send($set1, 'delete', 'orange');

print "Orange Total=" . &send($set1, 'how_many', 'orange') . "\n";
&send($set1, 'dump');
&send($set1, 'show_self');

print "** bag **\n";
&send($bag1, 'put', 'banana');
&send($bag1, 'put', 'apple');
&send($bag1, 'put', 'orange');
&send($bag1, 'put', 'orange');
&send($bag1, 'put', 'orange');

print "Orange Total=" . &send($bag1, 'how_many', 'orange') . "\n";
&send($bag1, 'dump');
&send($bag1, 'show_self');

&send($bag1, 'delete', 'orange');

print "Orange Total=" . &send($bag1, 'how_many', 'orange') . "\n";
&send($bag1, 'dump');
&send($bag1, 'show_self');
@//E*O*F sample3//
chmod u=rwx,g=rwx,o=rx sample3
 
echo x - sample4
sed 's/^@//' > "sample4" <<'@//E*O*F sample4//'
#/usr/bin/perl
require 'stack.pl';

# create two instances of class 'stack'
$s1 = &newobject('stack');
$s2 = &newobject('stack');

# push items onto stack $s1
&send($s1, 'push', 10);
&send($s1, 'push', 20);
&send($s1, 'push', 30);

print "top of stack 1=" . &send($s1, 'top') . "\n";
print "--- dump of stack 1 ---\n";
&send($s1, 'dump');

&send($s2, 'push', 'Hello, world.');
print "top of stack 2=" . &send($s2, 'top') . "\n";

print "--- show me ---\n";
&send($s1, 'show_self');
print "--- show me ---\n";
&send($s2, 'show_self');

&send($s1, 'pop');
print "top of stack 1=" . &send($s1, 'top') . "\n";

&send($s1, 'pop');
print "top of stack 1=" . &send($s1, 'top') . "\n";

&send($s1, 'pop');
print "top of stack 1=" . &send($s1, 'top') . "\n";
@//E*O*F sample4//
chmod u=rwx,g=rwx,o=rx sample4
 
echo x - sample5
sed 's/^@//' > "sample5" <<'@//E*O*F sample5//'
#/usr/bin/perl
require 'point.pl';

$msgtrace = 1; # message trace on

# create a point @ (10, 20) ... see 'init' method
$p1 = &newobject('point', 10, 20);
&send($p1, 'show_self');

&send($p1, 'move', 100, 100);
&send($p1, 'show_self');

&send($p1, 'rmove', 20, 20);
&send($p1, 'show_self');
@//E*O*F sample5//
chmod u=rwx,g=rwx,o=rx sample5
 
echo x - sample6
sed 's/^@//' > "sample6" <<'@//E*O*F sample6//'
#/usr/bin/perl
require 'operl.pl';

# define new class 'hello' as subclass of 'root'
&defclass ('hello', 'root');

# 'init' method will be invoked on creating an object
&defmethod('hello', 'init', '$i = 0;');

# method 'add1' adds 1 to $i
&defmethod('hello', 'add1', '$i++;');

# method 'show' shows the value of $i
&defmethod('hello', 'show', 'print "-> " . $i . "\n";');

# define new class 'hello2' as subclass of 'hello'
&defclass ('hello2', 'hello');

# method 'add2' adds 2 to itself (send add1 to self twice)
# you can refer to the current object as $self
&defmethod('hello', 'add2', <<'METHOD' );
	&main'send($self, 'add1');
	&main'send($self, 'add1');
METHOD

$o1 = &newobject('hello2');

&send($o1, 'show');
&send($o1, 'add2');
&send($o1, 'show');
@//E*O*F sample6//
chmod u=rwx,g=rwx,o=rx sample6
 
exit 0
--
 sakoh@sra.co.jp
"Whereof one cannot speak, thereof one must remain silent."  ---Wittgenstein
"Sometimes noise is significant."                            ---William Hewlett