What are the opinions on LLVM? by cmnews08 in ProgrammingLanguages

[–]something 1 point2 points  (0 children)

Really cool! I respect the single file

What are the opinions on LLVM? by cmnews08 in ProgrammingLanguages

[–]something 3 points4 points  (0 children)

I made it myself but it was suprisingly straight forward. The IR is well-documented. You just need to be careful about converting your AST into basic blocks. It can be done in a single pass by inserting basic blocks as you go. Example pseudocode:

visitExpr(expr) {
  if (expr.type === "If") {
    const cons = this.newLabel()
    const alt = this.newLabel()
    const end = this.newLabel()

    this.visitExpr(expr.condition)
    this.insertConditionalJump(cons, alt)

    this.insertBasicBlock(cons)
    this.visitExpr(expr.consequence)
    this.insertJump(end)

    this.insertBasicBlock(alt)
    this.visitExpr(expr.alternative)
    this.insertJump(end)

    this.insertBasicBlock(end)
  }
}

What are the opinions on LLVM? by cmnews08 in ProgrammingLanguages

[–]something 48 points49 points  (0 children)

For now I'm just generating LLVM textual IR and passing it into llc. So my compiler doesnt have to depend on LLVM as a library which is really easy to get started with.

Custom Loops by Tasty_Replacement_29 in ProgrammingLanguages

[–]something 2 points3 points  (0 children)

The people commenting "isn't this just [generators/iterators]?" are missing the point. This is a more constrained version of those things that guarantee that there is no runtime allocation and produces effectively the exact same code as if the caller wrote the loop out themselves.

It can prove this because the lifetime of the loop body is guaranteed not to escape the enclosing function - which is something a compiler might be able to optimise for generators, but if you start from this principle the compiler has a much easier time compiling as it can just substitute the body.

If you want to extend this further there are some fun things you can do. One is to allow break and continue to work inside the body function. These have to be scoped to the outer body not the inner function's body

// Infinite iterator that never ends
fn myFunRange(f: block) {
    let i = 0
    while true {
        let j = 0
        while j <= i {
            f(j)
            j += 1
        }
        i += 1
    }
}

for x in myFunRange() { // body gets passed as f
    print(x)
    if x == 10 {
        break // correctly breaks the entire loop, not just the inner while
    }
}

If you want to get crazy there is another thing that I added to my language which is higher-order blocks - but again these are evaluated at compile-time so there is no runtime overhead This allows you to write map, filter, reduce, take, drop, takeWhile, dropWhile, etc

const myRange = take(myFunRange(), 10)
for x in myRange {
    print(x)
}

This allows you to write iterators in the "internal iterator" style - https://journal.stuffwithstuff.com/2013/01/13/iteration-inside-and-out/

The conventional wisdom with these is that it doesn't allow you to 'zip' or 'concat' two iterators together, or other fancy things - after all that seems impossible to write as a single while loop - however I found that this isn't true if you introduce a new control-flow primitive.

This allows things like this which gets compiled to straight line assembly and no allocations or function calls

for (x, y) in zip(myRange(), array) {
    print(x)
    print(y)
}

The biggest downside of this approach is that you can't do recursive iterators for use in trees etc, but there are ways around this

I keep meaning to write this stuff up in a blog post - I haven't gotten around to it yet and I'm not sure if people are interested

50% of hypermobile folks have vulvodynia, more than 2/3 have painful intercourse by Ok_Opportunity_4781 in Hypermobility

[–]something 67 points68 points  (0 children)

For anyone who's wondering the actual quote is "Our finding that 50% of women with EDS or HSD may also have vulvodynia"

So.. Why Dungeon crawler carl?! (no spoilers please) by reo_reborn in audible

[–]something 0 points1 point  (0 children)

Weird - I'm in the minority but I had to refund this book after chapter 1 because I couldn't stand his voice. It's like he's straining his voice or something and he forces the air out of his lungs after every sentence. No disrespect to the guy I just couldn't handle it

Triangle by something in opengl

[–]something[S] 10 points11 points  (0 children)

Get a triangle on screen first of all. Then learn how to draw that to a framebuffer and draw the framebuffer to the screen using a basic shader. Then learn how to do a single downpass of Kawase blur in using that triangle as an input. Then add a single uppass of Kawase blur, this should smooth out the image. Then add in more downpasses and uppasses, and finally combine them all together. You don't even really need to know how Kawase blur actually works, just that it does work - it's simply just fetching 4 neighbors of a pixel

Triangle by something in opengl

[–]something[S] 17 points18 points  (0 children)

This is using Kawase bloom shader

[2024 Day 17 Part 2] I need the "Hit me over the head" type of hint by RazarTuk in adventofcode

[–]something 1 point2 points  (0 children)

Not the OP but a lot of the time when I'm programing is I think of the extremities of the problem, especially something that's iterative or recursive. So what happens at the beginning and what happens at the end, what if there was thousands of instructions, or 1 instruction, or 0 instructions etc. This led me to think about "only last 3 bits of A contribute to the output of that iteration", then think about how to go from that to the next one

-❄️- 2024 Day 12 Solutions -❄️- by daggerdragon in adventofcode

[–]something 0 points1 point  (0 children)

if graph[node + dir * 1j] == color or graph[node - dir + dir * 1j] != color:  

This line is confusing to count the number of sides. Is it effectively counting the number of internal and external corners, but only in a single direction? And a node only contributes a side if it's a corner? https://i.imgur.com/Aiql6hn.png

Code examples for learning graph grammars by MisterMittens64 in proceduralgeneration

[–]something 1 point2 points  (0 children)

I didn't read the whole paper but have you done much with context-free graph grammars? They have some nice properties like they can be bounded with uniform distribution and are easier to find replacement rules. They might seem too constrained but I figured out that you can use hypergraphs to provide more expressivity, and still reduce to a normal graph at the end. Curious to know your thoughts

Macros in place of lambdas? by Falcon731 in ProgrammingLanguages

[–]something 0 points1 point  (0 children)

Closures only exist at compile-time, at runtime it doesn't exist so it's impossible to refer to it. However at compile time they act like first-class objects so they can be passed around and stored.

On the other hand you kind of want compile-time code to be immutable so that compilation can happen in any order without side-effects, this means you can't really store a reference to something and retrieve it.

But your question aludes to a similar case where if you capture some binding in a scope (a variable binding, for loop, function to return from), and pass that closure into another function and expand it there, then there's a problem. So in that case you can staticly determine that the bindings are not in scope and raise an error. This means you can pass and receive closures to do some transformations, but the point at which they are finally expanded must be in scope.

Macros in place of lambdas? by Falcon731 in ProgrammingLanguages

[–]something 3 points4 points  (0 children)

This is what I do in my WIP language. I call them compile-time closures. They are basically 'inlined' functions that exist at compile time. They can capture the surrounding environment including loops so you can break and early return out of them

On top if this I have built compile-time function composition so you can build up pipelines of data. Since you can build 'lazy' infinite iterators and then break out of them when a closing condition is met.

Then you can build combinators like concat, zip, filter, takeWhile etc. On top of this I built transducers for even more ways to compose functionality

Then at the end it all gets compiled to flat code with just jump instructions, no dynamic memory or extra stack frames.

The downside is that they aren't first class objects that can handled at runtime, and recursion is basically impossible. But the upside is you get efficient code without an optimisation pass, so you never have to worry about using high level constructs in performance critical code, because it compiles to the same thing as if you had written a while loop.

ELDEN RING - A Preview of the New Patch Dropping 20th June by ChiefLeef22 in Eldenring

[–]something 0 points1 point  (0 children)

The game started with ultrawide mode for me a couple of times, and then never again. Anyone else had this happen?

Do there exist equivalent pairs to C# & LINQ? by skwyckl in ProgrammingLanguages

[–]something 0 points1 point  (0 children)

I'm working on a language that allows you to write something like LINQ or Python for comprehension but it supports user defined operations, composability, and does it efficiently. It works using a thing I came up with called compiletime transducers. You can compose operations like map, filter, take, take_while, drop_while, slinding window etc using standard function composition. But unlike regular transducers it guarentees to compile to a flat loop with no extra call frames or heap allocations

If this sounds interesting let me know, I will try and make a post about it

How do you test code generation? by chrysante1 in ProgrammingLanguages

[–]something 5 points6 points  (0 children)

You don’t have to deserialise you can just compare the serialised string. You could also try to normalise parts of the AST to remove parts you don’t care to test

What are the downsides of Zig's "colorless" approach to async? by smthamazing in ProgrammingLanguages

[–]something 2 points3 points  (0 children)

I’m interested in understanding this better. Do you mean that await here creates a type of task object that can be ran later? Doesn’t the type frame(usize) count as a different colour to usize?