cvsuser 03/11/24 20:02:16
Modified: imcc/docs imcfaq.pod
Log:
Add a couple OOP related questions that will be useful until
we get classes/objects finished in Parrot.
Also apply typo patches from Jerome Quelin ([EMAIL PROTECTED])
Revision Changes Path
1.2 +150 -5 parrot/imcc/docs/imcfaq.pod
Index: imcfaq.pod
===================================================================
RCS file: /cvs/public/parrot/imcc/docs/imcfaq.pod,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -w -r1.1 -r1.2
--- imcfaq.pod 24 Nov 2003 06:53:16 -0000 1.1
+++ imcfaq.pod 25 Nov 2003 04:02:16 -0000 1.2
@@ -199,13 +199,13 @@
$I2 = $I1 * 3
-This uses symbolic STRING and INTVAL registers as temporaries. This is they typical
sort of code
+This uses symbolic STRING and INTVAL registers as temporaries. This is the typical
sort of code
that compilers generate from the syntax tree.
=head3 Named Variables
Named variables are either local, global or namespace qualified. Currently IMCC only
-supports locals transparently, however globals are support in an explicit syntax.
+supports locals transparently, however globals are supported with explicit syntax.
The way to declare locals in a subroutine is with the B<.local> directive. The
B<.local> directive
also requires a type (B<int>, B<num>, B<string> or a classname such as
B<PerlArray>).
@@ -222,7 +222,7 @@
=head2 How do I declare global or package variables in IMC?
-You can't yet. IMCC still lacks a few features and these are one of those features.
+You can't yet. IMCC still lacks a few features and this is one of those features.
You can explicitly create global variables at runtime, however, but currently it
only works for PMC types, like so:
@@ -286,8 +286,8 @@
This one is very simple. Use the B<.include> directive to include other .imc source
files. Do keep in mind that currently Parrot starts execution with the first
-sub it sees in the bytecode; so if your main includes external .imc files it needs
-to include them after the your "main" start sub. If you .include them first (in
+sub it sees in the bytecode; so if your main includes external .imc files you need
+to include them after your "main" start sub. If you .include them first (in
typical C or Perl style, Parrot will execute the first sub in the first included
source file. This is because B<.include> is a preprocessed directive and simply
creates
one huge .imc source module.
@@ -392,6 +392,151 @@
.pcc_begin_return
.pcc_end_return
.end
+
+=head2 How can I compile classes and objects?
+
+Parrot and IMCC do not YET support pre-compiled classes and objects. Until
+the support is added, you can easily achieve it, you just need to do it all
+dynamically.
+
+Write support routines for new and construct and generate your constructors
+as simple subroutines. I suggest some sort of simple name mangling (C++/Java)
+when naming the subs (_TestClass__print_i). Your compiler will need
+to track field (or member) offsets in the array, or if you want to
+be even lazier and give up a tiny amount of speed, use a hash and you don't
+have to track them.
+
+
+=head2 That sounds easy, but how would it look?
+
+I'd be surpised if you are writing a compiler and can't figure this one out by
+yourself, but I'll be nice since this IS supposed to be documentation.
+It does help to actually see how IMCC does it.
+
+Remember, you only have to use Parrot's builtin mechanisms if your language
+wishes to interact with other languages, otherwise you can implement high level
+constructs any way you wish. You'll have to for a while longer, anyway.
+
+The exercise for a destructor is left up to you. You'll quickly notice that
+supporting destruction with Parrot's garbage collection requires a bit of
+support from the internals that currently just isn't there. But we plan to get
+there soon. By the time we DO get there, you won't need the syntax below.
+
+=head3 An OOP Example
+
+Hypothetical language Mython, (apologies to Python, but it sure is nice and brief):
+
+ class TestClass:
+ int i
+ method init:
+ i = 0
+ method print_self:
+ printf "%d\n", i
+
+ sub main:
+ TestClass obj1, obj2
+ obj1 = new TestClass
+ obj2 = new TestClass
+ obj1.i = 1
+ obj2.i = 2
+ obj1.print_self()
+ obj2.print_self()
+
+
+Here is the IMCC workaround until we have explicit .class syntax and bytecode
freeze/thaw.
+
+ .sub _main
+ .local pmc obj1
+ .local pmc obj2
+ .local pmc meth
+ _init_world() # _init() sets up all classes and globals
+ obj1 = __new("TestClass") # obj1 = new TestClass;
+ __ctor(obj1)
+ obj2 = __new("TestClass") # obj2 = new TestClass;
+ __ctor(obj2)
+ obj1[4] = 1 # obj1.i = 1;
+ obj2[4] = 2 # obj1.i = 2;
+ P2 = obj1 # obj1.print_self()
+ meth = obj1[3]
+ invokecc meth
+ P2 = obj2 # obj2.print_self()
+ meth = obj2[3]
+ invokecc meth
+ end
+ .end
+
+ # Called only once upon program start
+ .sub _init_world
+ .local SArray c
+ .local Sub meth
+ .local PerlString classname
+ classname = new PerlString # class TestClass:
+ c = new SArray
+ c = 10 # Array size 10
+ global "classes::TestClass" = c
+ classname = "TestClass"
+ c[0] = classname
+ meth = global "_TestClass_ctor" # method init:
+ c[2] = meth
+ meth = global "_TestClass_print_self" # method print_self:
+ c[3] = meth
+ $P100 = new PerlInt # int i
+ c[4] = $P100
+ # TestClass is now defined, instantiate away
+ # Setup any other globals for program
+ .pcc_begin_return
+ .pcc_end_return
+ .end
+
+ # This is generic infrastructure code
+ .sub __new
+ .param string classname
+ $S1 = "classes::" . classname
+ # Instantiate a TestClass
+ $P11 = global $S1
+ P2 = clone $P11 # Clone does a copy, including
members
+ .pcc_begin_return # Return the new "object"
+ .return P2
+ .pcc_end_return
+ .end
+
+ # This is generic infrastructure code
+ .sub __ctor
+ .param pmc self
+ # Call TestClass constructor
+ $P100 = self[2]
+ P2 = self # For method calling convention P2 is the object
+ invoke $P100 # Leave P1 with ret continuatio (tail chain)
+ .pcc_begin_return
+ .pcc_end_return
+ .end
+
+ .sub _TestClass_init # method TestClass.init
+ .local pmc self
+ .local pmc classname
+ .local Integer i
+ self = P2
+ classname = self[0]
+ print classname
+ print "::constructor\n"
+ self[4] = 0 # self.i = 0;
+ .pcc_begin_return
+ .pcc_end_return
+ .end
+
+ .sub _TestClass_print_self # method TestClass.print_self
+ .local pmc self
+ .local pmc i
+ self = P2
+ i = self[4] # printf ("self.i = %d\n", i)
+ print "self.i = "
+ print i
+ print "\n"
+ .pcc_begin_return
+ .pcc_end_return
+ .end
+
+
=head1 Thats not all.