Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How do I associate methods with a compiler?

9 views
Skip to first unread message

Patrick R. Michaud

unread,
Nov 8, 2006, 9:58:43 PM11/8/06
to perl6-i...@perl.org
Historically Parrot has considered a compiler to be an
invokable subroutine, such that the canonical sequence for
compiling something is:

.local string perl6_source
.local pmc perl6_compiler
perl6_compiler = compreg 'Perl6'
$P0 = perl6_compiler(perl6_source)

However, pdd21_namespaces.pod says that compilers have
methods such as 'parse_name', 'get_namespace', and 'load_library'
(see the section titled "Compiler PMC API").

Recognizing that much of the details about compilers are still to
be specced, the naive version of my question is: "How do we get
those API methods (and possibly other compiler-specific methods)
attached to the compiler sub?"

Or, in claiming that compilers have an API, should we instead
say that the canonical compilation sequence is to use compreg
to obtain a compiler object (not an invokable sub), and then
compile the source via a 'compile' method on the compiler object?
For example:

perl6_compiler = compreg 'Perl6'
$P0 = perl6_compiler.'compile'(perl6_source)

In asking the above questions I'm purposely avoiding, because Parrot
doesn't seem to support it yet, the possibility that the object
obtained via compreg is both invokable in its own right (like a sub)
and has methods attached to it. I'm simply curious as to how we
conceptually model "compilers" in Parrot -- are they really like
subroutines or are they more traditional 'objects' that provide
a method-based interface for invoking a compilation.

Opinions welcome. Personally I think I favor the "a compiler is
an object with a 'compile' method" model, and that C<compreg> gives
us back a compiler object as opposed to a subroutine-like thing.

Thanks in advance,

Pm

Adriano Rodrigues

unread,
Nov 9, 2006, 6:55:05 AM11/9/06
to perl6-i...@perl.org
On 11/9/06, Patrick R. Michaud <pmic...@pobox.com> wrote:
> Opinions welcome. Personally I think I favor the "a compiler is
> an object with a 'compile' method" model, and that C<compreg> gives
> us back a compiler object as opposed to a subroutine-like thing.

Would it not be possible to support both? A compiler compiles, so it
seems natural to write quick-and-dirty compilers as simple
subroutines. Also for wrappers around other compiler codes, they still
could be useful if they compile/execute, while there is not a
full-blown implementations in terms of the Parrot compiler API .

The usage patterns could be something like:

.local string perl6_source
.local pmc perl6_compiler
perl6_compiler = compreg 'Perl6'
$P0 = perl6_compiler(perl6_source)

(Yes, the same as Patrick's first snippet.) And then

perl6_compiler = compreg 'Perl6', OBJ # OBJ is some constant


$P0 = perl6_compiler.'compile'(perl6_source)

"compreg S" would be short for "compreg S, SUB" or something (and it
could be always required). While "compreg S, OBJ" may blow with a "non
implemented feature for some compilers". It would be easy for object
compilers to provide a sub implementation. But on the other hand it
could also be easy for subroutine compilers to provide an object
implementation with the help of a wrapper object (with not very useful
methods besides 'compile').

My $0.02 cents.

Adriano Ferreira.

Patrick R. Michaud

unread,
Nov 9, 2006, 11:00:14 AM11/9/06
to Adriano Rodrigues, perl6-i...@perl.org
On Thu, Nov 09, 2006 at 09:55:05AM -0200, Adriano Rodrigues wrote:
> On 11/9/06, Patrick R. Michaud <pmic...@pobox.com> wrote:
> >Opinions welcome. Personally I think I favor the "a compiler is
> >an object with a 'compile' method" model, and that C<compreg> gives
> >us back a compiler object as opposed to a subroutine-like thing.
>
> Would it not be possible to support both?

Sure, it's possible to support both -- we can even handle both
types within the existing Parrot framework. I think I'm basically
asking which model will be considered the "Parrot standard"?

> The usage patterns could be something like:
>
> .local string perl6_source
> .local pmc perl6_compiler
> perl6_compiler = compreg 'Perl6'
> $P0 = perl6_compiler(perl6_source)
>
> (Yes, the same as Patrick's first snippet.) And then
>
> perl6_compiler = compreg 'Perl6', OBJ # OBJ is some constant
> $P0 = perl6_compiler.'compile'(perl6_source)

We could do this now without requiring an additional parameter
to C<compreg>, by adding suffixes to the compiler name. For example:

$P0 = compreg 'Perl6_sub' # get subroutine view of compiler
$P0 = compreg 'Perl6_obj' # get object

But I find the suffix (or the use of an extra parameter) a bit
overblown. I'd rather come up with a standard API for compilers
that supports all of this, and then individual compiler subs can
deviate from that standard if it's really appropriate.

I've also just written a HLLCompiler base class (I would've called
it 'Compiler', but that name is currently taken in Parrot) that
makes it easy to wrap a sub into a compiler object. Thus
registering a new compiler becomes:

load_bytecode 'Parrot/HLLCompiler.pbc'

.local pmc compile_object, compile_sub
compile_object = new [ 'HLLCompiler' ]
compile_sub = get_global 'name_of_compile_sub'
compile_object.'compsub'(compile_sub)
compreg 'MyCompiler', compile_object

Using the compiler is then:

.local pmc mycompiler
mycompiler = compreg 'MyCompiler'
$P0 = mycompiler.'compile'(source)

Thanks for the excellent comments!

Pm

Allison Randal

unread,
Nov 14, 2006, 11:52:47 PM11/14/06
to Patrick R. Michaud, perl6-i...@perl.org
Patrick R. Michaud wrote:
>
> Or, in claiming that compilers have an API, should we instead
> say that the canonical compilation sequence is to use compreg
> to obtain a compiler object (not an invokable sub), and then
> compile the source via a 'compile' method on the compiler object?
> For example:
>
> perl6_compiler = compreg 'Perl6'
> $P0 = perl6_compiler.'compile'(perl6_source)

Also for the record from the weekly meeting (which was actually today,
just a very long today): Yes, compilers are objects and compilation is a
method call. The compiler for TGE tree grammars is implemented this way,
and it's a very usable interface.

We might want to resurrect the 'compile' opcode as an indirect syntax
for making the 'compile' method call.

> In asking the above questions I'm purposely avoiding, because Parrot
> doesn't seem to support it yet, the possibility that the object
> obtained via compreg is both invokable in its own right (like a sub)
> and has methods attached to it.

Possible, but agreed that it's more complex than we need, without enough
added gain to be worth it.

Allison

Patrick R. Michaud

unread,
Nov 15, 2006, 12:01:06 AM11/15/06
to perl6-i...@perl.org
On 11/9/06, Patrick R. Michaud <pmic...@pobox.com> wrote:
> Opinions welcome. Personally I think I favor the "a compiler is
> an object with a 'compile' method" model, and that C<compreg> gives
> us back a compiler object as opposed to a subroutine-like thing.

For the record, it was decided (Allison++) during today's
#parrotsketch meeting that the convention would be to have
the 'compreg' opcode return an object with a 'compile' method,
as opposed to returning an invokable sub.

Of course, individual language implementors may choose to
defy convention, and for the forseeable future the "PIR"
and "PASM" compilers that come with Parrot will continue
to be subroutine-like. All of this just means that
callers to compreg need to know what they are getting back
or else figure it out at runtime.

I'm hoping to formalize some of the details for creating
compilers into a "compilers pdd" at some not-too-distant date.
Comments and suggestions welcomed. At the moment we have
the following:

- There's a HLLCompiler class (loadlib 'Parrot/HLLCompiler.pbc')
that can be used to quickly create compiler objects.

- To register a new compiler using HLLCompiler:

load_bytecode 'Parrot/HLLCompiler.pbc'
.local pmc compile_sub, mycompiler

## get the compilation subroutine
compile_sub = get_global 'compile'

## create a new compiler object
mycompiler = new [ 'HLLCompiler' ]

## register the language and compiler subroutine
mycompiler.'register'('MyCompiler', compile_sub)

- To perform a compile:

mycompiler = compreg 'MyCompiler'
$P0 = mycompiler.'compile'('...source code...')

In addition, HLLCompiler provides a 'command_line' method
for acting as a standalone compiler; thus a .pir/.pbc can
simply have its :main sub delegate control directly
to HLLCompiler. For example:

.sub main :main
.param pmc args

.local pmc mycompiler
mycompiler = compreg 'MyCompiler'

mycompiler.'command_line'(args)
.end

When invoked in this manner, compiler object will compile
and execute any source file given on the command line, or
enter an interactive mode if no source file is given.
The result of the compilation can be controlled by the
--target command line (assuming the compilers involved
support this):

--target=parse # output parse tree
--target=past # output ast (PAST)
--target=post # output opcode tree (POST)
--target=pir # output PIR

HLLCompiler also understands '--encoding' (for languages that
have specific character encoding requirements), and '--output'
to specify a file where the output should be placed.

Comments and other feedback are greatly appreciated.

Thanks!

Pm

Patrick R. Michaud

unread,
Nov 15, 2006, 12:15:46 AM11/15/06
to Allison Randal, perl6-i...@perl.org
On Tue, Nov 14, 2006 at 08:52:47PM -0800, Allison Randal wrote:
>
> Also for the record from the weekly meeting (which was actually today,
> just a very long today): Yes, compilers are objects and compilation is a
> method call. The compiler for TGE tree grammars is implemented this way,
> and it's a very usable interface.

Our messages crossed in the mail.

> We might want to resurrect the 'compile' opcode as an indirect syntax
> for making the 'compile' method call.

Maybe, but I can't see that this is worthy of a special opcode
(and presumably a vtable slot?). There's just not a lot of
difference between:

$P0 = compile mycompiler, code # compile opcode
$P0 = mycompiler.'compile'(code) # Parrot convention

Another advantage of using (true) method calls is that
it's easy to pass options and additional arguments to the
compiler:

$P0 = mycompiler.'compile'(code, 'target'=>'parse')

Pm

Allison Randal

unread,
Nov 15, 2006, 2:02:19 PM11/15/06
to Patrick R. Michaud, perl6-i...@perl.org
Patrick R. Michaud wrote:
>
>> We might want to resurrect the 'compile' opcode as an indirect syntax
>> for making the 'compile' method call.
>
> Maybe, but I can't see that this is worthy of a special opcode
> (and presumably a vtable slot?). There's just not a lot of
> difference between:
>
> $P0 = compile mycompiler, code # compile opcode
> $P0 = mycompiler.'compile'(code) # Parrot convention

The main reason is to have a consistent interface that can be used to
compile code whether that code is PASM, PIR, or one of the HLLs. But, a
lot depends on how the Compiler PDD develops. It seems likely that the
best solution will be to have the PASM and PIR compilers act like
standard compiler objects.

Allison

Leopold Toetsch

unread,
Nov 15, 2006, 4:15:52 PM11/15/06
to perl6-i...@perl.org, Allison Randal, Patrick R. Michaud
Am Mittwoch, 15. November 2006 05:52 schrieb Allison Randal:
> We might want to resurrect the 'compile' opcode as an indirect syntax
> for making the 'compile' method call.

Please don't. Opcodes are very limited re calling conventions. Mehthods are by
far more flexible when it comes to pass arguments to compilers.

And compiling a piece of code isn't one of the fast operations a CPU can do,
it doesn't warrant an dedicated opcode.

leo

Allison Randal

unread,
Nov 15, 2006, 4:38:32 PM11/15/06
to Leopold Toetsch, perl6-i...@perl.org
Leopold Toetsch wrote:
>
> Please don't. Opcodes are very limited re calling conventions. Mehthods are by
> far more flexible when it comes to pass arguments to compilers.

I believe we've been through this conversation before. I don't mean
coding a completely different opcode, I just mean using the opcode
syntax to make (a standard form of) the method call.

And, I do think making the PASM and PIR compilers capable of being used
as standard compiler objects is a superior solution.

Allison

Leopold Toetsch

unread,
Nov 15, 2006, 5:07:49 PM11/15/06
to perl6-i...@perl.org, Allison Randal
Am Mittwoch, 15. November 2006 22:38 schrieb Allison Randal:
> Leopold Toetsch wrote:
> > Please don't. Opcodes are very limited re calling conventions. Mehthods
> > are by far more flexible when it comes to pass arguments to compilers.
>
> I believe we've been through this conversation before. I don't mean
> coding a completely different opcode, I just mean using the opcode
> syntax to make (a standard form of) the method call.

Yes. But abstracting opcodes syntax to some method isn't implemented
generally. It can be done, as experiments in src/builtin.c are showing. But I
don't see any good reason to implement new features with some opcode syntax,
when it'll be a method call anyway.

> And, I do think making the PASM and PIR compilers capable of being used
> as standard compiler objects is a superior solution.

We currently can't pass any arguments to PASM/PIR compilers. You can't change
trace or debug options for "eval". This is a serious limitation, which needs
a flexible solution e.g. passing named args. Some syntactic sugar opcode
syntax, which first has to be parsed as opcode, then be converted to a method
call does really not help here - sorry.

> Allison

leo

Allison Randal

unread,
Nov 15, 2006, 8:52:32 PM11/15/06
to Leopold Toetsch, perl6-i...@perl.org
Leopold Toetsch wrote:
>
>> And, I do think making the PASM and PIR compilers capable of being used
>> as standard compiler objects is a superior solution.
>
> We currently can't pass any arguments to PASM/PIR compilers. You can't change
> trace or debug options for "eval". This is a serious limitation, which needs
> a flexible solution e.g. passing named args. Some syntactic sugar opcode
> syntax, which first has to be parsed as opcode, then be converted to a method
> call does really not help here - sorry.

Hrm... I think you missed my point, which was that enabling method-call
syntax on the PASM/PIR compilers was a better solution than pushing
consistency via opcode syntax.

We're in violent agreement again. :)

Allison

0 new messages