The following program correctly fails to compile:
sub f(Int $a) { my Str $b = $a }
say f 42;
say f 'foo';
Specifically, line 3 causes a compilation error (with a ===SORRY!===
error message); this error occurs before line 2 is executed, so the type mismatch within &f is never reached.
But when, specifically, does this error occur? I thought it occurred during the CHECK phase, but was surprised to notice that raku -c
does not generate a compile error; it reports Syntax OK
.
To dig into this a bit more, I added logging code to the snippet above:
BEGIN note 'begin';
CHECK note 'check';
INIT note 'init';
END note 'end';
sub f(Int $a) { my Str $b = $a }
say f 42;
say f 'foo';
Running this revised code with raku -c
prints "begin\n check\n Syntax OK"; running it with raku
prints "begin\n check\n ===SORRY!===" (and the rest of the error message).
If I remove the say f 'foo'
line (and thus the compile error), raku -c
still prints "begin\n check\n Syntax OK" but raku
prints "begin\n check\n init\n Type check failed… \n end" (again omitting the body of the error message).
What's going on here? Does the compile error that generated the ===SORRY!===
occur some time between CHECK and INIT (is there any such time?)? Or does raku -c
not actually "run BEGIN and CHECK blocks" as raku --help
indicates? Or something else?
Relatedly: how, if at all, is any of this connected to the idea of "nested compile times"? Does the execution of this code involve any nested compile times, or does that only occur when using modules? Is there any way to note/log separate compile phases (maybe with correctly placed BEGIN blocks?) or is that something that isn't exposed?
There are the various phases of compiler: Lexical analyzer phase is the first phase of compilation process. It takes source code as input. It reads the source program one character at a time and converts it into meaningful lexemes. Lexical analyzer represents these lexemes in the form of tokens.
This is the final stage of compilation. The optimized code is converted into relocatable machine code which then forms the input to the linker and loader. All these six phases are associated with the symbol table manager and error handler as shown in the above block diagram.
The compilation process contains the sequence of various phases. Each phase takes source program in one representation and produces output in another representation. Each phase takes input from its previous stage.
However, because of the same, the execution time is way more than a similar program written in a compiled platform-dependent program. Consider simple printing program is written somewhere on the local directory in a machine.
The SORRY message is a side-effect of the static optimizer. Observe the difference in behaviour between:
$ raku -e 'sub foo(Int $a) { }; foo "foo"'
===SORRY!=== Error while compiling -e
Calling foo(Str) will never work with declared signature (Int $a)
and:
$ raku --optimize=off -e 'sub foo(Int $a) { }; foo "foo"'
Type check failed in binding to parameter '$a'; expected Int but got Str ("foo")
in sub foo at -e line 1
which happens somewhere between CHECK
and INIT
time, unless it has been disabled. Note that disabling the static optimizer makes it a runtime error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With