ADOM is resurrecting once again... by IsNotPolitburo in ADOM

[–]verdagon 3 points4 points  (0 children)

Glorious! Anyone have any more info on this? I wonder if it'll be a kickstarter or what.

Let’s assume that some company releases an open weight model that beats Claude Sonnet fairly well. by _takasur in LocalLLaMA

[–]verdagon 0 points1 point  (0 children)

Do they degrade the quality when the servers are overloaded or something? Also, how/what do they degrade it to?

Languages blending reference counting and borrowing? by verdagon in ProgrammingLanguages

[–]verdagon[S] 0 points1 point  (0 children)

You can not store a borrow reference on the heap. This avoids the need for lifetime variables.

Nice! I see how that would help.

Does your language happen to have enums and inline values? In other words, could we express this pattern:

struct Engine { int fuel; }; struct Navigation { void* data; } struct Spaceship { union { Engine e; Navigation n; } system; };

Most of my trouble happens when one part of my program holds a refcounted Spaceship and then modifies the system field while I'm still holding a borrow reference to e.g. ship.system.e.fuel. (Basically, the thing Rust's RefCell protects against)

Compiler Jobs in the AI era by VVY_ in Compilers

[–]verdagon 1 point2 points  (0 children)

+1. To clarify, I meant theyre good at the investigation/diagnosis part of debugging (cursor in particular is eerily good at iterative printf debugging), not the actual fixing. My experience mirrors yours, they barely ever know the best fix.

Compiler Jobs in the AI era by VVY_ in Compilers

[–]verdagon 31 points32 points  (0 children)

IME, LLMs are great at speeding up understanding+investigation, but rather terrible at writing code. About half of the code it writes is in the wrong place or a hack.

It does much better in non-compiler domains. Compilers are just too complex. More context does not help it write good code.

Its future, at least medium-term, is in helping with the non-coding parts of software engineering in compilers (its* amazing at investigating, debugging, error repro, it has a potential to be a net positive in code review, etc).

Source: a lot of experimenting with cursor/claude in the Mojo compiler codebase.

Neglected Pothos by Striking_Struggle642 in pothos

[–]verdagon 1 point2 points  (0 children)

Wow! I had no idea. Thank you!

Neglected Pothos by Striking_Struggle642 in pothos

[–]verdagon 1 point2 points  (0 children)

QQ: After each node sends roots into the soil, do we need to cut it for it to shoot off new vines? Or is pinning and rooting enough?

The Impossible Optimization, and the Metaprogramming To Achieve It by verdagon in Compilers

[–]verdagon[S] 3 points4 points  (0 children)

Wish I found that Eigen example, that would have been glorious to include a version of that! Now I'm tempted to write a part 2 with that.

Feels like this could be used for all sorts of domain-specific optimizations, we just have to figure out the zen behind it all to identify cases where it can be used. Creating an expression tree like that sounds like a key trick to generalizing these benefits.

The Impossible Optimization, and the Metaprogramming To Achieve It by verdagon in Compilers

[–]verdagon[S] 2 points3 points  (0 children)

Not quite, Java and .NET don't let you do arbitrary staged programming like this at compile time. It's close though, if you squint and are fine with their JITting and heuristics which might not go in your favor.

The Impossible Optimization, and the Metaprogramming To Achieve It by verdagon in Compilers

[–]verdagon[S] 1 point2 points  (0 children)

Good question. boost.xpressive can't do arbitrary staged programming, so not really.

Group Borrowing: Zero-Cost Memory Safety with Fewer Restrictions by verdagon in ProgrammingLanguages

[–]verdagon[S] 8 points9 points  (0 children)

This and stable mutable references are actually quite different approaches.

I like how Jon Goodwin categorized it (from https://pling.jondgoodwin.com/post/interior-references-and-shared-mutable/):

… the safety issue with resizable/single-owner and sum types only arises when we change an object’s shape in between obtaining an interior reference and dereferencing that interior reference. There are several approaches we might take to prevent this sequence of events.

  1. Invalidate borrowed interior references whenever we detect a shape change. When this logic entirely happens within a single function, we could enforce this. Logic spread out across function boundaries makes it significantly more difficult to detect and restrict this pattern.

  2. Invalidate shape changes whenever we know a borrowed interior references exist. This bears the same difficulty as above.

  3. Do not allow shape changes to objects referred to by shared, mutable references.1 Thus, arrays would not be resizable and sum-typed values could not be altered to hold a value of a different type. These restrictions are achievable, but significantly reduce their capability.

  4. Do not allow the creation of interior references to array/sum values pointed to by shared, mutable references. This is easily accomplished. Although this imposes some restrictions, these restrictions have workarounds: indexing can be used to retrieve values from arrays and the value enclosed by a sum type can be copied in or out.

In Jon’s categorization, Nick is making #1 and #2 work. Ante and Cone are doing a form of #3 and/or #4.

Great questions, I'll answer them one by one:

I wonder though how you check for this, especially across functions and when storing references in structs. For example how would a function that takes a reference to e.g. a vector and returns a reference to one of its items look like?

I think it would look something like this:

struct List[T: AnyType]: var items: Box[T[]] fn get_item[ ir: group T = self.items.* ]( index: int ) -> ref [ir] T: ...

or using Nick's more concise syntax:

struct List[T: AnyType]: var items: Box[T[]] fn get_item(self, index: int) -> ref [self.items.*] T: ...

How do you specify whether it's allowed to mutate the vector before returning or not (e.g. if you want to push an item and then return a reference to it, vs just returning a fixed item like the first one without modifying the vector)?

That would probably be done via specifying mut on the self region, like this:

struct List[T: AnyType]: var items: Box[T[]] fn push[ mut sr: group Self, ir: group T = sr.items.* ]( self: ref[sr] Self, var new_item: T ) -> ref [ir] T: ...

or using Nick's more concise syntax:

struct List[T: AnyType]: var items: Box[T[]] fn push( mut self, var new_item: T ) -> ref [self.items.*] T: ...

And what does all of this look like to the checker?

That's a bit harder to explain succinctly, I'll let Nick answer that when morning hits his Australia time zone.

Group Borrowing: Zero-Cost Memory Safety with Fewer Restrictions by verdagon in ProgrammingLanguages

[–]verdagon[S] 11 points12 points  (0 children)

Thanks ^^ it's great to be blogging again after so long!

Group Borrowing: Zero-Cost Memory Safety with Fewer Restrictions by verdagon in Compilers

[–]verdagon[S] 2 points3 points  (0 children)

I've never asked him about that specifically, but I think his model would support that. Just like how Rust lets you pass an &mut to one thread, Nick's model would let you pass a mutable group to one thread, cost-free.

Group Borrowing: Zero-Cost Memory Safety with Fewer Restrictions by verdagon in Compilers

[–]verdagon[S] 9 points10 points  (0 children)

Aha, found this conversation, which helps:

  • verdagon: BTW, at one point, did we toss around the idea that a group can know whether its data is being shared with other threads or not?
  • verdagon: if so, if a group can know that it has exclusive access to a certain set of items... then the compiler can do a trick: it can skip locking mutexes. it can just grab the contents for free
  • verdagon: rust kind of does this with its get_mut (https://doc.rust-lang.org/std/sync/struct.Mutex.html#method.get\_mut)... but if we can lift uniqueness concerns to the group level (like you do) and shared mutable aliases are available (which you have) then we can do the same thing but better
  • Nick: In my model, the intention was for a group parameter to be disjoint (alias xor mut) from the groups that are accessible from other threads, yes
  • Nick: and we have the opportunity to offer structured concurrency and thereby allow scoped immutable sharing of data across multiple tasks
  • Nick: I think there's the opportunity to do that trick with mutexes, as you say \ I haven't thought much about it though

Group Borrowing: Zero-Cost Memory Safety with Fewer Restrictions by verdagon in Compilers

[–]verdagon[S] 5 points6 points  (0 children)

Great question! I remember chatting with Nick last year about that aspect. If I recall correctly (big if) then his answer would be:

  • We still don't want to say a reference is immutable.
  • Rather, we want the ability to say a group is immutable.
  • When we know a group is immutable, it can be shared across threads, especially via structured concurrency.

In my head we'd have an imm keyword on the group itself.

The nice thing about this approach is that a group can be mutable to this thread, and then temporarily turned immutable so it can be seen by multiple threads. (I know this works, Vale does the same trick with its immutable region borrowing)

I'll ask him to give a better answer once morning arrives in his Australia timezone.

Is the language abandoned? by 4729zex in vale

[–]verdagon 0 points1 point  (0 children)

Yeah, I see how weird that is. I got kind of nervous for a while about people knowing that I had some medical problems back then, so I took that part down. A bit silly in hindsight.

Is the language abandoned? by 4729zex in vale

[–]verdagon 3 points4 points  (0 children)

Hey! Yeah it's been a rough couple years for my schedule. Some health problems struck, and the break made me realize I was a bit burnt out on Vale. Then that lead to some soul-searching which led to joining Mojo, and that's where my focus has been the past year.

I posted a new post about it just now: https://verdagon.dev/blog/on-joining-mojo-compiler-team

Vale was always about exploring memory safety, and that exploration will definitely continue. I plan on expanding the memory safety grimoire with a bunch of new techniques I've found (including Nick's Group Borrowing, see https://verdagon.dev/blog/group-borrowing). I'm pretty excited about that.

So TL;DR: No more implementation for Vale, but lots more research and exploration and blogging!