5

Let's say I want to create a number of types at compile-time, but before that let's test compile-time code with a simpler example:

# in file root.pm6
sub foo($a) { $a.say }

sub EXPORT {
    # Things here may be a lot more complex
    foo 1;
    foo 2;
    foo 1;
    %( one => 1 )
}

and a module between direct original library and end-user file:

# in file middle.pm6
use root;
class A {} # Do something with stuff from root.pm6

End-user file:

# in file user.pm6
use middle;

Then in command line:

➜  tester perl6 -I. user.pm6
1
2

It seems that third call to foo was cached and wasn't executed for the third time.

Such behavior makes any relatively complex computations(that are based on code re-use) in sub EXPORT(as well as in other compile-time areas) impossible.

According to my understanding, compile-time code is meant to be executed normally with its results(e.g. some declarations, tweaks and so on) being accessible from the compiled unit by other modules. However, there is some sort of caching involved too.

The question is, ultimately, "How to achieve what I want" with possible milestones:

1)Is such sort of caching intended?

2)If yes, can it be disabled while having advantages of compile-time code execution? If no, what another workarounds are possible?

UPDATE 1: explaining thing I want more specifically: at compile-time I am parsing a config file and creating types to export. I want those to be pre-compiled, that is the point. Types can be nested and various cases are possible, so I am handing in with a transitional state machine imitation implemented as a simple subroutine with a long given-where statement, some branches are recursive(bottom is always present). The issue I stuck at is that some branches won't be executed after being fired once, which I was able to golf into simple double foo 1 call I have presented in main question.

UPDATE 2: as raiph mentioned, it works correctly when ran from a command line when level of indirectness between original lib and user-one is 0, but when structure is root lib file that creates types -> middleware lib file that patches those -> end-user(be it a test file or another module, not all code is executed.

Takao
  • 1,016
  • 6
  • 11
  • 1
    I've only read your question's title not its body. So this might be useless, but have you seen [`no precompilation;`](https://docs.perl6.org/language/pragmas#precompilation)? Also, see [Constants are computed at compile time](https://docs.perl6.org/language/traps#Constants_are_computed_at_compile_time). – raiph Jan 07 '19 at 00:12
  • 2
    as for those two: 1)in fact, I _want_ stuff to be precompiled, it is a whole point of my work here. 2)as for constants - yes, but I am not really sure it is related. – Takao Jan 07 '19 at 00:17
  • @Takao I don't see a difference between "precompiled" and "cached". Precompilation creates a precomp cache in the (default) `.precomp` dir. If you want to test-compile them you can use perl6 -c, but that also implies precompilation. Maybe you should be looking at a different phaser instead of EXPORT, although I understand you want your variables exported, but there are different ways of achieving that. – jjmerelo Jan 07 '19 at 09:07
  • 2
    I just tried your code outside of the REPL and got `1␤2␤1␤`, i.e. it worked as I would expect. – raiph Jan 07 '19 at 09:45
  • 2
    Indeed, it is. However, it doesn't work like so when level of indirectness is more than 2(i.e. lib -> lib -> lib), with first one uses precompilation. I will update the question. – Takao Jan 07 '19 at 11:33

2 Answers2

4

This appears to be a Rakudo bug or something close enough to it.

At least, as advised by Jonathan Worthington, using note instead of say makes the example code work as necessary, which clears all implications being made about possible caching being involved.

Takao
  • 1,016
  • 6
  • 11
3

Maybe you are looking at the INIT phaser:

INIT {
    # Things here may be a lot more complex
    foo 1;
    foo 2;
    foo 1;
    %( one => 1 ) 
}

Which might be a bit too verbose for you:

> use user;
1
2
1
2
1

INIT is run at runtime. If you want to assign values to variables, it will get the job done.

jjmerelo
  • 22,578
  • 8
  • 40
  • 86