🦋 Welcome to the IRC channel of the core developers of the Raku Programming Language (raku.org #rakulang). This channel is logged for the purpose of history keeping about its development | evalbot usage: 'm: say 3;' or /msg camelia m: ... | Logs available at irclogs.raku.org/raku-dev/live.html | For MoarVM see #moarvm
Set by lizmat on 8 June 2022.
Geth nqp/main: 82425cb36c | (Justin DeVuyst)++ | tools/templates/MOAR_REVISION
Bump MoarVM for release testing
02:23
rakudo/main: a9843ca5ad | (Justin DeVuyst)++ | tools/templates/NQP_REVISION
Bump NQP for release testing
02:24
02:49 MasterDuke left 03:00 MasterDuke joined 04:32 MasterDuke left 07:16 sena_kun joined 07:32 sena_kun left
ab5tract okay, it's feeling a bit clearer this morning 07:53
but one question for you nine: is the role that adds the custom dispatcher meant to be applied on the proto for splice, or on the specific revision-gated candidates? 08:04
or should I just add the custom dispatcher method in bootstrap at the same time that I add the item_disambiguation flag?
08:05 donaldh left
nine Excellent questions. I don't know exactly. I figure, this should become part of the existing multi dispatcher as then we can have just some candidates for old behavior and some for new and otherwise you won't notice that they exist. That however sounds a bit intimidating. So maybe we'll punt that for now and put the custom dispatcher on the proto and e.g. dispatch to a different proto (i.e. set of 08:08
multi-candidates) depending on the language version 08:09
I'd certainly try the easiest way at first, because there's already enough to figure out, like how to access that lexical with the language version. And when we have something working, we can think about optimal solution. 08:10
ab5tract Hmm… in fact it might be simplest to put a role on the proto *and* on the relevant candidates. That way the custom dispatcher would just filter out all candidates gated above the caller’s language revision 08:17
Also, it’s worth considering whether this approach puts the end to the JVM implementation, or if we are content to use the current approach in the PR for that case 08:38
nine The JVM is gonna need a dispatcher implementation eventually. Until then the current approach should be fine. 08:49
ab5tract It really needs a serious revisit. I think we could probably get a fair amount of traction out of newer JVM features. The new threading model especially 09:01
It was written targeting Java 8, if I’m not mistaken? 09:03
Anyway, maybe I’ll pick that up at some point… it would also be much more competitive if it were a “JVM native” language that could (in theory) load libraries from other languages, though I’m not sure I if that’s actually feasible with 6model as the basis 09:06
nine Yeah, since I've picked up Scala, I have gained a lot more appreciation for the JVM 09:10
ab5tract Indeed. Even Java itself is quite usable once you have streams and records 09:15
09:30 dawids joined 09:31 dawids left 09:56 nine left, nine joined
patrickb I don't want to demotivate work on the JVM backend (I do love that we have a pluggable backend!) but (oh well...) I strategically want to have an Inline::Java thing (and am willing to work on it at one point). 10:08
ab5tract That would call into JVM via NativeCall? 10:11
patrickb Yes 10:13
The approaches are orthogonal. Inline::* connects different VMs while supporting more backends introduces Raku to other VMs. 10:15
ab5tract Right, which is why I was confused about how this would affect motivation for the JVM backend 10:17
patrickb Both approaches allow mixing Raku and Java in a single project. 10:40
So if there is a well working Inline::Java there is less incentive to move the JVM backend forward as there already is a way to reach for the Java ecosystem. 10:41
Geth rakudo/main: 7907eeab18 | (Elizabeth Mattijsen)++ | src/core.c/RakuAST/Deparse.rakumod
RakuAST: adapt test for hidden "will build" trait
ab5tract Fair. My primary motivation to move the JVM forward is because I’m tired with maintaining a second backend that is only semi-functional and unwieldy, so that shouldn’t be an issue :) 10:45
Also, it’s ultimately unclear whether the backend can ever integrate other JVM languages and libraries, which means (a version of) Inline::Java could still be useful 10:47
releasable6 Next release in ≈3 days and ≈7 hours. There are no known blockers. Please log your changes in the ChangeLog: github.com/rakudo/rakudo/wiki/ChangeLog-Draft 11:00
Geth rakudo/main: 09a96033ca | (Elizabeth Mattijsen)++ | 2 files
RakuAST: make highlighting tests pass

So that they're not a blocker for 2024.08 release
  - fix several issues with highlighting, e.g. with "use v6.x" and
   using a << or « as an opener for markup
  - mark several failing tests as todo for now
11:09
11:13 [Coke] left 11:16 [Coke] joined
jdv blin said "🥞🥞 No regressions found" 12:27
lizmat whee! 12:30
13:20 finanalyst joined
lizmat and yet another Rakudo Weekly News hits the Net: rakudoweekly.blog/2024/08/26/2024-...ro-💍-htmx/ 13:29
[Coke] Dr Raku‘s (open single quote instead of apostrophe?) 13:38
also: lizmat++! 13:43
(nifty: my terminal realizes the link was a URL, but the emoji confused it, the link stopped with cro- - but then the blog saw the partial and redirected it to the full URL. 13:46
lizmat heh... always ready to start a confusion :-) 13:49
notable6: weekly 13:53
notable6 lizmat, No notes for “weekly”
15:00 finanalyst left
ab5tract nine: I'm running into major obstacles while trying to set up a trait to apply a role onto the relevant method candidates.. 15:23
I guess it's related to Array being compiled so early in the CORE.c.setting stage, but I would have thought everything necessary would already be in bootstrap 15:25
For example, given: `multi sub trait_mod:<is>(Routine:D $r, :$revision-gated!) {` 15:27
I can't even call `die "got $revision-gated"` because it complains that Match doesn't exist in the CORE setting 15:28
same failure if I try to call `nqp::istype($revision-gated, Match)` (also tried with `NQPMatch`) 15:29
If I put in a call to `nqp::what($revision-gated)`, I get `Method 'protect' not found for invocant of class 'Any'` 15:30
lizmat yeah, bootstrapping is fun :-(
timo protect, so it's trying to hold a Lock that isn't initialised yet?
well, created / assigned 15:31
ab5tract but it's a call to `nqp::what`, so I don't understand why there would be any HLL dependencies involved whatsoever 15:32
lizmat nqp::what wouldn't do a lock or anything?
ab5tract hmm, I hadn't yet tried just a completely empty bodied version of this trait
lizmat: it shouldn't do a lock using HLL components, unless I've misunderstood the separation of concerns 15:33
lizmat yeah, so it's something else that's causing the error, I'd say ?
ab5tract it look like it's the call to `die` itself 15:34
lizmat not where the "die" is called ? 15:35
ab5tract with an empty body, there's no issues with the trait. but as soon as I try to attach a role to the routine that is passed in (even using static values and ignoring the Match That Doesn't Exist in Core Yet), I get VMnull failures from $*W.apply_trait 15:36
lizmat in RakuAST? 15:37
ab5tract kind of a weird boot-strap-a-roo
lizmat: unfortunately I can't test in RakuAST because we can't compile core setting yet
lizmat ack 15:38
that early in the setting, types that don't exist, don't generate any compile time errors, in my experience
their WVals are just not initialized, and so calling anything on them will cause a VMNull error
could it be a typo somewhere ?
ab5tract I will double check that, but the surface area is pretty compact 15:39
lizmat a typo would be my first guess
ab5tract `$r.^mixin: role { has $.required-revision = $internal-revision; method REQUIRED-REVISION(--> Int) { $!required-revision } }`
lizmat where does $internal-revision come from? 15:40
ab5tract It *should* be based on the input, so `is revision-gated("6.e")` would create a version object and count the elements in the range from `"c"` to `$version.parts[{$_ - 1}]` (WhateverCodes are also not working at this stage :) ) 15:42
but for testing I've set it manully on the line above
I've also tried using it as a parameter on the role and also as a punned constructor or whatever `R($this-is-ssigned-to-the-first-public-attribute)` is called 15:44
nine Can you gist the patch? 15:45
ab5tract sure, one moment. there's a bunch of comments that will indicate what all I've tried so far 15:46
gist.github.com/ab5tract/6bf842c70...f4cbf5e601 15:49
Failure for the current patch content is: `Could not locate compile-time value for symbol &trait_mod:<will>` 15:50
lizmat line 10: the dd will never work there
ab5tract lizmat: it has
nine I was just gonna ask since when we have dd in nqp
lizmat aaah.... yes, I added dd to nqp a while ago 15:51
I think?
nine Apparently since May :D
ab5tract works just fine when there is no content in the trait_mod definiton
lizmat m: dd Array.splice 15:52
camelia Cannot resolve caller splice(Array:U: ); none of these signatures matches:
(Array:D \SELF:: *%_ --> Array:D)
(Array:D $:: Whatever, *%_ --> Array:D)
(Array:D $:: Callable:D $offset, *%_ --> Array:D)
(Array:D $:: Int:D $offset, …
ab5tract note that it doesn't fire with the current code, though I've seen it fire with other configurations of the trait_mod body
timo ab5tract: do you need some assistance in running moar under gdb and maybe rr to figure all this out?
ab5tract I've gotten a bit of experience with `lldb` earlier this year, but I will definitely take you up on that if it comes to such a thing. 15:54
nine Well that dd in traits.rakumod at least cannot work
ab5tract At the moment it feels very surface-y
it's commented out, correct?
nine + dd :traits(@traits.grep({ trait-name($_) eq "revision-gated" })), :$subtype; 15:55
nope
timo there's some debug helpers that are functions you can just call with "call" or "print" inside of the gdb repl. MVM_dump_backtrace(tc) and MVM_dump_bytecode(tc) are the ones i use most commonly
and i assume call and print are the same in lldb
ab5tract ah, it doesn't work but it doesn't cause any issues either
I've just confirmed 15:56
nine My favourite debug tool:
+QAST::MASTOperations.add_core_op('note', -> $qastcomp, $op {
+ $qastcomp.as_mast(
+ QAST::Op.new(
+ :op('call'),
+ QAST::Op.new( :op('gethllsym'), QAST::SVal.new(:value('nqp')), QAST::SVal.new(:value('note')) ),
+ $op[0]
+ )
+ )
+});
in src/vm/moar/QAST/QASTOperationsMAST.nqp
Then nqp::note($some-string). Works absolutely everywhere with no bootstrap issues 15:57
Needs nqp::bindhllsym('nqp', 'note', &note); in src/core/IO.nqp
ab5tract can we include this op? 15:58
timo: yeah, there's similar functionality in lldb. one cool technique I learned was how to put conditionals onto breakpoints, that saved a lot of time 15:59
nine That early in the setting not even infix:sym<~> will be defined, so "revision-gated = " ~ nqp::what($revision-gated).Str is a VMNull call
timo yes, conditional breakpoints are absolutely essential 16:00
nine OTOH that's just a call to a post-declared sub, so it should actually work 16:01
timo does it happen inside a trait mod execution?
ab5tract it seems strange that the bootstrap is sufficient for DEPRECATED to work 16:02
but not for this new one, which does almost exactly the same in practice 16:03
timo: it's commented out but yeah I was trying to debug it
*with it
lizmat ab5tract: perhaps because Attribute is already functional from the bootstrap ? 16:05
ab5tract I meant this candidate: `multi sub trait_mod:<is>(Routine:D $r, :$DEPRECATED!) {` 16:06
unless I'm misunderstanding you?
nine: it does seem that calls to `is raw` and `is nodal` are succeeding just fine at this point in the bootstrap, so it's possible that I could set a flag or a field on the routine object instead of mixing in a role. 16:08
That feels less smooth though... I guess another option is to put this down and see what things would look like in a RakuAST-driven bootstrap?
16:09 dawids joined
ab5tract (put this down for now, I mean) 16:09
lizmat Rakudo::Deprecations is stubbed, maybe you forgot to stub something?
ab5tract It may require a separate module for tracking, but the similarity I was talking about is that both revision-gated and deprecated create a role and mix it into a routine 16:13
but yeah, the lack of a stub would be one of those invisible error thingies like a typo at this bootstrap level, right?
maybe implementation-detail is a better comparison 16:14
nine > ./rakudo-m -e 'sub foo() is revision-gated(1) {}; say &foo.REQUIRED-REVISION' 16:20
1
@@ -416,6 +416,11 @@ multi sub trait_mod:<returns>(Routine:D $target, Mu:U $type) {
$sig.set_returns($type);
$target.^mixin(Callable.^parameterize($type))
}
+multi sub trait_mod:<is>(Routine:D $r, :$revision-gated!) {
+ $r.^mixin(
+ role is-revision-gated[$r] { method REQUIRED-REVISION() { $r } }.^parameterize($revision-gated) 16:21
+ );
+}
ab5tract nailws ir~ 16:24
nailed it! 16:25
thanks nine... maybe I would have made it there, at some point :)
`Method 'parametrize' not found for invocant of class 'Perl6::Metamodel::ParametricRoleHOW'` :( 16:36
lol, ok that's a clear PEBKAC :) 16:40
16:41 sena_kun joined 16:44 dawids left
ab5tract anyone know why Array.splice was lacking a proto? 16:49
without one, even the revised trait dies due to not being able to find an archetype
nine I'd guess Array inherits that proto from Any 17:31
ab5tract ah, and of course that's too early for the trait :S 17:50
maybe I can add a BEGIN block to grab the proto and mix in the the trait 17:52
nine core_epilogue.rakumod is a good place for that 18:02
ab5tract am I right in thinking that the only way to check for proto is where @!dispatchees exists? 18:05
nine Yes, that's ultimately what makes a proto a proto 18:27
18:51 dawids joined 19:18 finanalyst joined
Geth rakudo: finanalyst++ created pull request #5632:
typo in documentation of Highlight.rakumod
19:50
ab5tract nine: there is an unfortunate complication to that definition 19:52
m: my &p = Any.^find_method(“splice”); dd candidates => &p.candidates; dd dispatchees => &p.dispatchees
camelia :candidates(())
:dispatchees(())
ab5tract But the proto to splice is clearly defined there, as you guessed earlier 19:54
Whereas, there is no proto defined here, but it also matches 19:56
m: my &p = [].^find_method(“splice”); dd candidates => +&p.candidates; dd dispatchees => +&p.dispatchees
camelia :candidates(31)
:dispatchees(31)
nine The proto on Array gets auto-generated as a "derived dispatcher" 20:00
ab5tract Right, so what’s the point of a proto on Any? And if checking for candidates / dispatchees can fail to reveal proto-ness, it seems that there should rather be a flag or attribute? 20:02
If the proto on Any is surpassed by the generated derived dispatcher, why not just provide a defined proto in Array? Why would a generated one be “allowed” but not a manually defined one? 20:06
nine Note that the definition of a dispatcher (proto) is not, whether it has any dispatchees, but whether it even has a @!dispatchees array (even if empty) 20:07
ab5tract Ah, ok, so that will be null on a non-proto 20:08
Geth rakudo/main: b46572e281 | (Stefan Seifert)++ | 3 files
RakuAST: fix nested packages shadowing their parents

When the parent package is not visible lexically, but through the global packages hierarchy, we ended up creating a new stub package lexically hiding the actual package. So search the global package hierarchy as well when trying to partially resolve the package name.
Fixes: { class Foo { }; }; class Foo::Bar is Foo { }; Foo::Bar.new
ab5tract Still seems like we could afford a helper sub in here, but that distinction helps
nine Not 100 % sure, but if someone adds candidates to the Any proto, they will probably be visible on Array, too
You mean is_dispatcher? :) 20:10
m: proto sub foo() { }.is_dispatcher.say
camelia True
nine m: sub foo() { }.is_dispatcher.say
camelia False
ab5tract I also don’t understand all these Any protos. Could we have a FALLBACK that dispatches to protos defined in more appropriate places instead? It might be a slight performance hit but that’s just for the weird attempts to call these methods on inapplicable objects.. 20:13
There’s literally no splice candidates without Array:D: 20:14
is_dispatcher looks perfect, thanks :) 20:15
nine Surprisingly Any is already the softened version. These protos used to live on Mu! 20:23
timo i think there's something wrong with our file handles in append mode. it could be a problem inside moar itself, though 20:25
the behaviour i'm seeing is this: i open a nonexisting file with :r, :w, :append, :create, :exclusive, :enc<utf8-c8> - i fill it with a couple of lines of text - when i seek to some earlier position and write, the return value from .tell() increases by the number of bytes written. of course, the actual data ends up at the end of the file. that is probably already wrong. additionally, calling 20:27
get() seems to act as if i called it before i wrote something, so i'm assuming the decoder has some bytes left in it
nine Huh.... the splice proto got moved to Mu from Array in commit 65959501d4a34d44016241f13503e1c7e4964886 20:28
linkable6 (2017-03-03) github.com/rakudo/rakudo/commit/65959501d4 Allow for native arrays in the settings
timo the tell method also looks at how many bytes are still in the decoder buffer to give its output, so that could also be a source of confusion 20:32
ab5tract Am I reading this commit message correctly in that the reason for the proto to shift to Mu was for bootstrapping?
timo and IO::Handle.seek is docced to not have a default value for $whence
but in the code it defaults to SeekFromBeginning 20:33
hum. default WRITE does not consider data stuck in a decoder 20:34
ab5tract timo: That sounds like an oversight.. 20:35
timo maybe there's even already a ticket open for this
of course it's super easy to shoot yourself in the foot with the combination of writing + encoder + seeking + decoder 20:37
ab5tract It reminds me of some recent movement in IO::Socket 20:38
timo r: given "/tmp/asdfgh.txt".IO.open(:r, :w, :enc<utf8>) { .put("hello") xx 5; .seek(0); .get() xx 2; say "middle position is $_.tell(); read line is $_.get.raku()"; .seek(6 * 2 + 3); say "second half of line $_.get.raku()"; .seek(6 * 2 + 3); .put("a!"); say "after writing, read $_.get.raku()"; } 20:40
camelia Can't open perl script "/home/camelia/rakudo-j-inst/bin/eval-client.pl": No such file or directory
middle position is 12; read line is "hello"
second half of line "lo"
after writing, read "hello"
timo m: given "/tmp/asdfgh.txt".IO.open(:r, :w, :enc<utf8>) { .put("hello") xx 5; .seek(0); .get() xx 2; say "middle position is $_.tell(); read line is $_.get.raku()"; .seek(6 * 2 + 3); say "second half of line $_.get.raku()"; .seek(6 * 2 + 3); .put("a!"); .seek(6 * 2 + 3); say "after writing and seeking back, read $_.get.raku()"; } 20:41
camelia middle position is 12; read line is "hello"
second half of line "lo"
after writing and seeking back, read "a!"
timo m: given "/tmp/asdfgh.txt".IO.open(:r, :w, :enc<utf8>) { .put("hello") xx 5; .seek(0); .get() xx 2; say "middle position is $_.tell(); read line is $_.get.raku()"; .seek(6 * 2 + 3); say "second half of line $_.get.raku()"; .seek(6 * 2 + 3); .put("a!"); .seek(6 * 2 + 3); say "after writing and seeking back, read $_.get.raku()"; .seek(0); say "everything: $_.slurp.raku()" }
camelia middle position is 12; read line is "hello"
second half of line "lo"
after writing and seeking back, read "a!"
everything: "hello\nhello\nhela!\nhello\nhello\n"
timo ok i think that looks reasonable? 20:42
m: given "/tmp/asdfgh.txt".IO.open(:r, :w, :append, :enc<utf8>) { .put("hello") xx 5; .seek(0); .get() xx 2; say "middle position is $_.tell(); read line is $_.get.raku()"; .seek(6 * 2 + 3); say "second half of line $_.get.raku()"; .seek(6 * 2 + 3); say "before writing fp at $_.tell()"; .put("a!"); say "after append-writing, fp is at $_.tell(); read $_.get.raku()"; .seek(0); say "everything: 20:43
camelia ===SORRY!=== Error while compiling <tmp>
Unable to parse expression in double quotes; couldn't find final '"' (corresponding starter was at line 1)
at <tmp>:1
------> .get.raku()"; .seek(0); say "everything:⏏<EOL>
expecting …
timo $_.slurp.raku()" }
dang haha
m: given "/tmp/asdfgh.txt".IO.open(:r, :w, :append, :enc<utf8>) { .put("hello") xx 5; .seek(0); .get() xx 2; say "middle position is $_.tell()"; .seek(6 * 2 + 3); say "second half of line $_.get.raku()"; .seek(6 * 2 + 3); say "before writing: $_.tell()"; .put("a!"); say "after append-writing: $_.tell(); read $_.get.raku()"; .seek(0); say "everything: $_.slurp.raku()" }
camelia middle position is 12
second half of line "a!"
before writing: 15
after append-writing: 63; read Nil
everything: "hello\nhello\nhela!\nhello\nhello\nhello\nhello\nhello\nhello\nhello\na!\n"
timo ok the file is still around from the previous run 20:44
m: given "/tmp/asdfgh.txt".IO.open(:r, :w, :append, :truncate, :enc<utf8>) { .put("hello") xx 5; .seek(0); .get() xx 2; say "middle position is $_.tell()"; .seek(6 * 2 + 3); say "second half of line $_.get.raku()"; .seek(6 * 2 + 3); say "before writing: $_.tell()"; .put("a!"); say "after append-writing: $_.tell(); read $_.get.raku()"; .seek(0); say "everything: $_.slurp.raku()" }
camelia middle position is 12
second half of line "lo"
before writing: 15
after append-writing: 33; read Nil
everything: "hello\nhello\nhello\nhello\nhello\na!\n"
timo ok, here the tell correctly jumps to the end? 20:45
let me golf locally some more 20:46
m: given "/tmp/asdfgh.txt".IO.open(:r, :w, :append, :truncate, :enc<utf8>, ) { .put("hello") xx 5; .seek(0); .get(); say "post-1st-line: $_.tell()"; .put("a!"); say "after append-writing: $(my $bp = .tell()); read $_.get.raku()"; .seek(0); say "everything: $_.slurp.raku()"; say "seek back to $bp and read:"; .seek($bp); say .get.raku; .close; .path.unlink; } 20:54
camelia post-1st-line: 6
after append-writing: 9; read "hello"
everything: "hello\nhello\nhello\nhello\nhello\na!\n"
seek back to 9 and read:
"lo"
timo there we go. you can see the .tell is 9, get gives "hello", but seek back to 9 and get gives you "lo", which is correct for the changed file pointer position, but i'm not so sure the file pointer should have moved at all 20:55
OK i can see that the tell result is wrong because before writing "a!\n" the file descriptor was already at EOF, but the decoder still had all the bytes from previous-position to previous-EOF in it, so calling .tell on the handle gives us the old position moved by how much the EOF position has moved 21:17
without :append, the stuff i .write also lands at the end of the file, but only because the decoder already slurped the entire file when i asked it to give me one line 21:40
i'm not sure it should actually be doing that though; IO::Handle!get-line-slow-path calls self.READ(0x100000), but I kind of feel like it should be $*DEFAULT-READ-ELEMS instead? 21:42
which defaults to 65536 if it's not in the environment, which is 0x10_000, compared to the 0x1_000_000 from !get-line-slow-path 21:44
linkable6: 7a2561c24bdde79b0369cc9bf7524899ffd54d89 21:47
linkable6 (2017-10-20) github.com/rakudo/rakudo/commit/7a2561c24b Revert "Implement knob to weak IO::Handle input buffer"
timo there briefly was a way to change how much it would read at once 21:48
oops, i put the _ wrong, it's actually 0x100_000 not 0x1_000_000 21:49
so only 16 times as much as the default read elems 21:50
default read elems is 64 KiB, what we read at once to get one line is 1 MiB 21:54
the readchars-slow-path also uses 1 MiB at a time 21:59
ab5tract timo: there is definitely an issue related to this 22:02
22:07 dawids left
ab5tract Can’t find it right now but iirc leont was a contributor to the ticket discussion. That dynamic var was mentioned as well 22:15
leont ab5tract: I suspect you mean github.com/rakudo/rakudo/issues/5189 22:16
ab5tract That’s it indeed 22:17
leont Really, we need primitives for both read(2) and fread(3) behavior. 22:18
"read up to X bytes" versus "read exactly X bytes unless EOF"
ab5tract Seems reasonable to me 22:29
leont (the first one is actually more like "read up to X bytes but at least 1") 22:50
22:57 sena_kun left 23:23 finanalyst left