On Aug-27, Leopold Toetsch wrote:
> Steve Fink wrote:
> >On Aug-26, Leopold Toetsch wrote:
> 
> >>.sub @regex_at_foo_imc_line_4711  # e.g.
> 
> >Yes, this illustrates what I was really getting at. My compiler can
> >certainly take a subroutine name (or file and line number, or whatever)
> >to use to generate the code with, but what is the proper way to pass
> >that infomation in through the compile op? 
> 
> I don't know how your compiler generates the code. But you are probably 
> concatenating a string of PIR instructions and pass that over to the 
> C<compile> opcode.
> Anyway, the identifier you are using for the C<.sub> directive gets 
> stored in globals and is the name of the subroutine.

Um... sorry, I was unclear. I am talking about how to get data *into* my
compile op. You are describing how to get it *out*, which I am well
aware of.

> >... I can just stick it in some
> >register, but it seems like there ought to be some standard-ish way of
> >passing parameters to compilers. Which then makes me wonder why compile
> >is done as an opcode rather than a method invocation on the return value
> >of compreg. 
> 
> C<compile> as a method call for the compiler would really be a 
> worthwhile extension. But you can provide your own compiler wrapper and 
> pass the subroutine name to that function. [1]

Yes, that is a reasonable way of implementing it. I probably wouldn't do
it exactly that way because I'd rather have the generated code be a
completely valid PIR snippet on its own -- in your example I would have
some orphaned ".param x" lines in what my compile op returned, which
would require the surrounding ".sub" to be valid. But it does
encapsulate things nicely, and makes it clear how to pass such
information in.

But that's not my issue. To stave off confusion, I should mention
here that I am not blocked on any of this; I can think of half a dozen
ways of doing what I want, now including the one you suggested. I am
now only asking these questions so that I might better write up a FAQ
entry, and what I am still unsure about is how to explain the purpose of
the compile op, and what the "official" way is to pass in parameters
that influence the compiled code. 


> >... I see that for Compiler and NCI PMCs, that's exactly what it
> >does, but for anything else it does the Parrot_runops_fromc_args_save
> >thing; couldn't that be somehow exposed separately so that the compile
> >op goes away? My only complaint about C<compile> is that it isn't
> >transparent how to use it, whereas I am comfortable with invoking things
> >and following the calling conventions.
> 
> Well, there isn't much difference. The compile function is called as a 
> plain function. A method call would additionally pass C<self>, which you 
> can pass as an argument too, if you need it.

Right. So why does the compile op exist? I assert that many compilers
will need some form of additional contextual information in order to
properly compile the code they are passed. My one example so far is the
key needed to ensure that the return Sub PMC is associated with a unique
name. This isn't a very good example, because it could be done wholly
within the compile op and therefore doesn't *really* need any
information passed in. However, there are many other examples: include
paths, library paths, optimization options, etc. It seems like there
ought to be a standard way of communicating this sort of information to
embedded compilers. Perhaps a way that is standard enough that the
language to be compiled could be treated as a dynamic parameter -- in
which case, all compilers would need interpret the passed-in contextual
information in the same way.

We already have one way of communicating information, and that is to use
the register calling conventions. If we really wanted different
languages' compilers to be able to interpret the same contextual
information (which is nice to have, but hardly a necessity), then we
would additionally need to specify a common signature -- perhaps to
compile something, you look up an invokable compiler PMC using
compreg, then "call" it with a single parameter representing named
arguments. Or something.

The question then becomes how to call the compiler. We could use the
C<compile> op, but it would be doing exactly the same thing as the
C<invoke> op, so why not just use that? If I look at the code, it shows
that there sometimes is a different between the two -- namely, if the
compiler PMC is anything than a Compiler or an NCI, then it calls
Parrot_runops_fromc_args_save rather than simply invoking it. Whatever
that function does, it must be necessary, so... why?  Then at last I
will understand why there is a need for a C<compile> separate from
C<invoke>.

Reply via email to