Author: allison
Date: Mon Feb 5 22:05:13 2007
New Revision: 16906
Modified:
trunk/compilers/smop/Attribute.pir
trunk/compilers/smop/Class.pir
trunk/compilers/smop/t/class.t
Log:
[smop]: Adding features and tests for attributes in the class constructor.
Modified: trunk/compilers/smop/Attribute.pir
==============================================================================
--- trunk/compilers/smop/Attribute.pir (original)
+++ trunk/compilers/smop/Attribute.pir Mon Feb 5 22:05:13 2007
@@ -40,7 +40,19 @@
.return(rv)
.end
+.sub type :method
+ .param pmc type :optional
+ .param int got_type :opt_flag
+ .local pmc rv
+ rv = self._accessor( "type", type, got_type )
+ .return(rv)
+.end
.sub init :vtable :method
$P0 = new String
setattribute self, "name", $P0
.end
+
+.sub init_pmc :vtable :method
+ .param pmc init_args
+ self.init()
+.end
Modified: trunk/compilers/smop/Class.pir
==============================================================================
--- trunk/compilers/smop/Class.pir (original)
+++ trunk/compilers/smop/Class.pir Mon Feb 5 22:05:13 2007
@@ -9,6 +9,17 @@
Classes are instances of the C<Class> PMC. Currently implemented in PIR,
but ultimately implemented as low-level .pmc.
+=head1 SYNOPSIS
+
+ .local pmc class, init_args, obj
+ init_args = new Hash
+ init_args['name'] = 'MyClass'
+ class = new 'Class', init_args
+# class = newclass 'MyClass'
+
+ class.add_attribute('myattribute')
+ obj = class.'new'( 'myattribute' => "Foo" )
+
=head2 find_class
This subroutine prototypes the C<find_class> opcode. It looks up a class
@@ -33,21 +44,13 @@
.local pmc class
class = newclass "Class"
addattribute class, "name"
+ addattribute class, "namespace"
addattribute class, "_parrotclass"
addattribute class, "attributes"
addattribute class, "methods"
addattribute class, "superclasses"
.end
-=head2 new
-
- .local pmc class, init_args
- init_args = new Hash
- init_args['name'] = 'MyClass'
- class = new 'Class', init_args
-# class = newclass 'MyClass'
-
-=cut
.sub init :vtable :method
$P0 = new Hash
@@ -77,6 +80,14 @@
.include "compilers/smop/_accessor.pir"
+=head2 name
+
+The accessor for the name attribute. With no argument, it simply returns
+the current value for name. When passed an argument, it sets the name of
+the class, and also sets the association with a namespace.
+
+=cut
+
.sub name :method
.param pmc name :optional
.param int got_name :opt_flag
@@ -88,21 +99,22 @@
store_global name, "class_object", self # namespace entry for class object
$P1 = newclass name
setattribute self, "_parrotclass", $P1 # dummy old-style class object within
- #$P0 = get_namespace [name]
- #$P1 = get_namespace
- #.local pmc initpmc
- #initpmc = get_global "_init_pmc"
- #print "but... but... "
- #say name
- #print "and "
- #say initpmc
- #store_global name, "_init_pmc", initpmc
- #$P0.add_sub("init_pmc", init)
+ $P1 = get_namespace
+ setattribute self, "namespace", $P1 # class entry for namespace object
get_only:
.return(rv)
.end
+=head2 new
+
+ obj = class.'new'( 'myattrib' => "Foo" )
+
+Create a new instance object from the class object. It takes an optional
+slurpy, named list of attributes and values to initialize the object.
+
+=cut
+
.sub 'new' :method
.param pmc args :slurpy :named
@@ -116,6 +128,14 @@
.return(obj)
.end
+=head2 attributes
+
+An accessor for the attributes attribute of the class. It returns the a
+Hash of all attributes, with a key of the attribute name, and a value of
+the Attribute object. The accessor is set by a hash of attributes, with
+a key name and a value type.
+
+=cut
.sub attributes :method
.param pmc attribs :optional
@@ -129,7 +149,8 @@
iter_loop:
unless iter goto iter_end
$S1 = shift iter # NOTE: convert to hash to add attribute types
- self.add_attribute($S1)
+ $P1 = iter[$S1]
+ self.add_attribute($S1, $P1)
goto iter_loop
iter_end:
@@ -138,14 +159,27 @@
.return(rv)
.end
+=head2 add_attribute
+
+Adds a single attribute to the class. It takes a simple string name, and
+a simple string value for type.
+
+=cut
+
.sub 'add_attribute' :method
.param string attribute_name
- .param pmc init_args :slurpy :named
+ .param string attribute_type :optional
+ .param int got_type :opt_flag
+
.local pmc new_attribute, attributes
- new_attribute = new 'Attribute', init_args
+ new_attribute = new 'Attribute'
new_attribute.'name'(attribute_name)
new_attribute.'class'(self)
+ unless got_type goto no_type
+ new_attribute.'type'(attribute_type)
+no_type:
+
# store the attribute in the class
attributes = getattribute self, 'attributes'
attributes[attribute_name] = new_attribute
Modified: trunk/compilers/smop/t/class.t
==============================================================================
--- trunk/compilers/smop/t/class.t (original)
+++ trunk/compilers/smop/t/class.t Mon Feb 5 22:05:13 2007
@@ -15,11 +15,16 @@
.IMPORT( 'Test::More', 'ok', _ )
.IMPORT( 'Test::More', 'is', _ )
- plan( 6 )
+ plan( 10 )
- .local pmc class, init_args
+ .local pmc class, init_args, init_attribs
init_args = new Hash
+ init_attribs = new Hash
+ init_attribs['ear'] = 'Str'
+ init_attribs['tail'] = 'Str'
init_args['name'] = 'Dog'
+ init_args['attributes'] = init_attribs
+
class = new 'Class', init_args # equiv to newclass 'Dog'
$P1 = class.name()
@@ -33,17 +38,38 @@
$I0 = exists attributes['bark']
ok($I0, "added attribute to the class")
+ $I0 = exists attributes['tail']
+ ok($I0, "added second attribute to the class")
+ unless $I0 goto no_tail_attribute
+ $P1 = attributes['tail']
+ $S1 = $P1.type()
+ is($S1,'Str', "tail attribute has a value")
+ goto end_tail_attrib_test
+ no_tail_attribute:
+ fail("tail attribute doesn't exist")
+ end_tail_attrib_test:
+
$P0 = find_class('Dog')
$I0 = issame $P0, class
ok($I0, "find_class can find the class")
- $P0 = class.'new'( 'bark' => "Wooof" )
+ $P0 = class.'new'( 'bark' => "Wooof", 'tail' => 'long' )
+ $P1 = getattribute $P0, "tail"
+ $I0 = defined $P1
+ ok($I0, "got back a tail attribute object")
+ unless $I0 goto SKIPTAIL
+ is($P1, "long", "tail attribute has expected value")
+ goto NEXTTAIL
+SKIPTAIL:
+ fail("SKIP - no attribute")
+NEXTTAIL:
+
$P1 = getattribute $P0, "bark"
$I0 = defined $P1
ok($I0, "got back a bark attribute object")
unless $I0 goto SKIP
- is($P1, "Wooof", "create object via Dog.new()")
+ is($P1, "Wooof", "bark attribute has expected value")
goto NEXT
SKIP:
fail("SKIP - no attribute")
@@ -77,3 +103,11 @@
rv = self._accessor( "bark", bark, got_bark )
.return(rv)
.end
+
+.sub tail :method
+ .param pmc tail :optional
+ .param int got_tail :opt_flag
+ .local pmc rv
+ rv = self._accessor( "tail", tail, got_tail )
+ .return(rv)
+.end