Remix.run Logo
steveklabnik 5 hours ago

I don't think you can draw the conclusion that source length and binary size are correlated. For example, in Rust:

    #[derive(Copy, Clone)]
    enum Expr {
        Int(i32),
        Add(i32, i32),
        Neg(i32),
    }
    
    fn eval(expr: Expr) -> i32 {
        match expr {
            Expr::Int(x) => x,
            Expr::Add(a, b) => a + b,
            Expr::Neg(x) => -x,
        }
    }
Rust's enums can carry data. You can write the same thing in C, but because it does not have the enum feature, you have to do it yourself. They're sometimes called "tagged unions" for a reason, you use a union + a tag when doing it by hand:

    #include <stdint.h>
    
    typedef enum {
        EXPR_INT,
        EXPR_ADD,
        EXPR_NEG,
    } ExprTag;
    
    typedef struct {
        ExprTag tag;
        union {
            struct {
                int32_t value;
            } Int;
    
            struct {
                int32_t left;
                int32_t right;
            } Add;
    
            struct {
                int32_t value;
            } Neg;
        };
    } Expr;
    
    int32_t eval(Expr expr) {
        switch (expr.tag) {
            case EXPR_INT:
                return expr.Int.value;
    
            case EXPR_ADD:
                return expr.Add.left + expr.Add.right;
    
            case EXPR_NEG:
                return -expr.Neg.value;
        }
    
        __builtin_unreachable();
    }
I haven't actually compiled this, but it should compile to almost the exact same, if not literally the exact same, machine code. Yet one is way more verbose than the other.
pavon 5 hours ago | parent | next [-]

I think you are saying the same thing as benced - just because Zig source code is verbose is no reason to assume the binary should be larger.

steveklabnik 5 hours ago | parent [-]

I read my parent ask asking a question: is there a correlation, or not?

I am saying that I do not believe there is a correlation between source code length and binary length. If that's what benced meant by their question, then yes, I agree :)

esjeon 5 hours ago | parent [-]

I’m quite sure there is a certain amount of correlation unfortunately, mainly because there are micro patterns (e.g. IO, allocator) that can’t be modularized into functions. Lots of manual copy-pasta.

14113 5 hours ago | parent | prev [-]

It required a little bit of messing with optimisation settings and library generation in Rust, but they emit very very similar x86-64 assembly:

https://godbolt.org/z/89W4srz4d

steveklabnik 5 hours ago | parent [-]

Nice, thank you for picking up after my laziness. Surely only a few bytes different in the binary, and much, much smaller of a delta than the source.

aw1621107 3 hours ago | parent [-]

You can further reduce the difference by passing Expr by pointer in the C version. At that point I think the only difference in the assembly is the order in which the cases are handed.

steveklabnik 2 hours ago | parent [-]

Ah yeah, honestly both should probably be passed by pointer anyway. But that makes me wonder about the actual differences here and why... maybe something fun to dig into.