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>.