# Copyright: 2001-2004 The Perl Foundation.  All Rights Reserved.
# $Id: compiler_faq.pod 7537 2005-02-15 14:56:12Z coke $

=head1 NAME

docs/compiler_faq.pod - Parrot FAQ for compiler writers

=head1 General Questions

=head2 Which C compilers can I use with Parrot?

Whoa, there--you're looking at the wrong FAQ.  This document is for people
writing compilers that target Parrot.

To answer your question, though, Parrot should theoretically work with any
C89-compliant C compiler, although some features require C<gcc>.  See the
F<README> files in the root directory for more information about building
Parrot.

=head2 How can I implement a compiler to use as a compiler object from within
Parrot? (For example, with the C<compile> op.)

=head2 How do I embed source locations in my code for debugging?

You can do this using the C<setfile> and C<setline> opcodes. Simply
set the source file name or line number whenever it changes. This is
sub-optimal for a number of reasons, so there should eventually be a
better system for this.

=head1 Subroutines

=head2 How do I generate a sub call in PIR?

If you have a fixed-length parameter list, IMCC makes this blindingly easy:

   $P0( $P1, $P2, $P3 )

where $P0 is the function object, and $P1, $P2, and $P3 are its
parameters. You can also use a function's label in place of the
object:

   somefunctionlabel( $P1, $P2, $P3 )

You can also get return value(s):

  ($P1,$P2) = $P0( $P1, $P2, $P3 )

=head2 How do I generate a method call in PIR?

Similar to function calls, just append C<.> and the method:

  ret_val = some_obj."some_meth"(arg)

The method name may also be a string variable representing a method name:

  .local string m
  m = "bold"
  curses_obj.m()

=head2 How do I generate a sub call with a variable-length parameter list in PIR?

Use unprototyped calls and functions and pass as many arguments as you have.
If you have a variable amounts of arguments in an array, you can pass all items
of that array with the C<.flatten_arg> directive.

  ar = new PerlArray
  push ar, "arg 1\n"
  push ar, "arg 2\n"
  .pcc_begin non_prototyped
  .flatten_arg ar
  .pcc_call sub
  ...

=head2 How to I retrieve the contents of a variable-length parameter list being passed to me?

You can check the passed PMC parameter count in the subroutine
with the argcP variable (an alias to I3). Remember, the first
eleven PMC parameters are passed in P5 through P15, with
overflow parameters an array-like PMC in P3.

A simpler way is to use the
C<foldup> opcode, which creates an array of all passed
PMC arguments.

  .sub _mysub non_prototyped
    .local pmc argv
    .local int argc
    argv = foldup
    argc = argv
    ...

If you have a few fixed parameters too, you can use a variant of
C<foldup> to capture variable arguments from that position on.

  .sub _mysub non_prototyped
    .param pmc arg0
    .param pmc arg1
    .local pmc varargs
    .local int num_varargs
    varargs = foldup, 2
    num_varargs = varargs
    ...

=head2 How do I create nested subroutines?

PIR doesn't support nested subroutines. You have to emit subroutines one by
one. If lexicals of the outer subroutine are visible inside the nested
sub, you have to include the outer pad depth in C<new_pad> opcodes.

=head1 Variables

=head2 How do I fetch a variable from the global namespace?

There are two possible ways.  Either use the special PIR syntax:

    $P0 = global "name_of_the_global"

or the C<find_global> op:

    find_global $P0, "name_of_the_global"

=head2 How do I use lexical pads to have both a function scope and a global scope?

To create lexical variables, you'll need to keep track of how deeply
nested each block of code is.  Say you have some HLL code like so:

    # depth 0
    lexical $bar
    $foo = 3       # global foo
    $bar = 5       # bar at depth 0
    {
      # depth 1
      lexical $foo
      $foo = 5     # foo at depth 1
      {
         # depth 2
         lexical $bar
         $foo = 7  # also foo at depth 1
         $bar = 2  # bar at depth 2
      }
      {
         # depth 2, again
         lexical $foo
         $foo = 11 # foo at depth 2
      }
    }

When you are building your program tree, have each block reference
its parent block, note its depth, and keep a list of all its lexical
variables.  At the opening of each block (that has lexical
variables), emit code to push a lexical pad:

    new_pad n

where C<n> is the lexical depth of the block. You can also use

    new_pad -1

to create a new pad with a nesting of C<outer + 1>.

At any point that you exit a block, you should emit

    pop_pad

This isn't necessary if you leave a block by invoking a continuation
(by C<return>ing from a subroutine, for instance), as the continuation will
automatically put the lexical pad stack back the way it was when the
continuation was created.

When you need to figure out how to access a certain variable, simply
look at the topmost block and work your way down the tree until you
finds a block that declares lexical variables. Then take the lexical
depth of the block in which you found it and emit some code like so:

    find_lex $P0, 2, "foo"

where C<2> is the depth the variable was found at, C<foo> is the name of the
variable, and $P0 is a PMC register in which to store the variable.

Note that, by convention (and confusing IMCC syntax), variables, not
direct values, are stored. So to assign to this lexical variable, you
would say:

    find_lex $P0, 2, "foo"
    assign $P0, some_value

instead of:

    store_lex 2, "foo", some_value

You will still need to do a C<store_lex> at some point (probably at the start
of the block in which it is declared) to create the variable in the first
place. Put a ParrotReference in it or something.

If, on the other hand, you never find said lexical variable (or if a
block declares that variable to be global, or whatever other tricks
your compiler likes to do), you might assume it to be a global, which you
can access much the same way:

    find_global $P0, "bar"
    assign $P0, value_to_store

=head2 How do I fetch a variable from the current lexical pad?

Use lexical depth -1:

    find_lex $P0, -1, "foo"

=head2 How do I fetch a variable from any nesting depth?

Omit the depth parameter:

    find_lex $P0, "foo"

This finds a C<foo> variable at any depth starting from the top.

=head2 How can I produce more efficient code for lexicals?

Use numeric indices instead of variable names for lexical retrieval. Lexicals
of one pad depth are numbered from 0..n-1 in the order of their declaration.

    find_lex $P0, -1, 0       # get first lexical from top pad
    find_lex $P1, -2, 3       # get forth lexical from next inner pad
    ...

=head1 Modules, Classes, and Objects

=head2 How do I create a module?

=head2 How do I create a class?

With the C<newclass> op:

    newclass $P0, "Animal"

=head2 How do I add instance methods to a class?

Methods are declared as functions in the class namespace with the
C<method> keyword appended to the function declaration:

  .namespace [ "Animal" ]

  .sub initialise method
    setattribute self, ...
    ...
  .end
  .sub run method
    ...
  .end

=head2 How do I add instance variables/attributes?

Each class knows what attribute its object can have. You can add
attributes to a class (not to individual objects) like so:

    addattribute $P0, "legs"

=head2 How do I access attributes?

Attributes can be access by a fully qualified name or by index.

  $P0 = getattribute self, "Animal\0legs"
  assign $P0, 4                   # set attribute's value

or

  .local int offs
  offs = classoffset "Animal"
  $I0 = offs + 0                  # 1st attribute
  $P0 = getattribute self, $I0
  $I0 = offs + 1                  # 2nd attribute
  $P0 = getattribute self, $I0

=head2 When should I use properties vs. attributes?

Properties aren't inherited. If you have some additional data that
don't fit into the classes hierarchy, you could use properties.

=head2 How do I create a class that is a subclass of another class?

You first have to get the class PMC of the class you want to subclass.
Either you use the PMC returned by the C<newclass> op if you created
the class, or use the C<getclass> op:

    getclass $P0, "Animal"

Then you can use the C<subclass> op to create a new class that is a subclass
of this class:

    subclass $P1, $P0, "Dog"

This stores the newly created class PMC in $P1.

=head2 How do I create a class that has more than one parent class?

First, create a class without a parent class using C<newclass> (or with only
one subclass, see previous question). Then add the other parent classes to it.
Please refer to the next question for an example.

=head2 How do I add another parent class to my class?

If you have a class PMC (created with C<newclass> or by C<subclass>), you can
add more parent classes to it with the C<addparent> op:

    getclass $P1, "Dog"
    subclass $P2, $P1, "SmallDog"
    getclass $P3, "Pet"
    addparent $P2, $P3  # make "SmallDog" also a "Pet"

=head2 How can I specify the constructor of a class?

You can specify the constructor method by setting the BUILD property of
the class PMC:

    newclass $P0, "Dog"         # create a class named Dog
    new $P1, .PerlString        # create a string
    set $P1, "initialise"       # set it to the name of the constructor method
    setprop $P0, "BUILD", $P1   # set the BUILD property

=head2 How do I instantiate a class?

First, you have to retrieve the type id of class you want to instantiate:

    find_type $I0, "Dog"

Then, you can create an instance of Dog with the new op:

    new $P0, $I0    # creates a Dog object and stores it in register $P0

During the C<new> opcode the constructor is called.

=head2 How can I pass arguments to an constructor?

You can pass only a single argument to a constructor.
By convention, a hash PMC is passed to the constructor that contains
the arguments as key/value pairs:

    new $P0, .PerlHash
    set $P0["greeting"], "hello"
    set $P0["size"], 1.23

    find_type $I0, "Alien"
    new $P1, $I0, $P0           # create an Alien object and pass
                                # the hash to the constructor

=head2 How do I add module/class methods?

=head2 How do I access module/class variables?

=head1 VERSION

=over 4

=item Revision 0.3 - 17 May 2004

=back
