Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> > compile-time execution of regular zig code

The problem with this is that it's incompatible with a well-designed compiled[0] programming language; a cross compiler can't replicate the architecture-specific behaviour of the compiled code because the target architecture is unavailable or possibly even nonexistent at the place and time the compiler runs.

Consider, eg, a compiler on ARM targeting x86, when the code uses x86-specific assembly or intrinsics, or more subtly depends on x86-specific handling of things like pointers or integer overflow. If you instead compile the compile-time code for ARM, you a: need two different codegens (soon to become three when you compile the compiler to run on RISC-V), and b: now the compile-time code is depending on ARM-specific semantics, which is even worse.

Giving up on cross compilers means your language isn't well-designed. Giving up on architecture-specific behaviour means your language isn't designed for (direct[0]) compilation. (The latter is a legitimate choice, of course, but its negation is also a legitimate choice, and thus a legitimate reason not to support same-language metaprogramming.)

0: in the sense of C-like compiling directly to equivalent machine code; obviously any language can be compiled in the more general sense of producing a working executable



> a cross compiler can't replicate the architecture-specific behaviour of the compiled code because the target architecture is unavailable or possibly even nonexistent at the place and time the compiler runs.

I mean, it can't possibly be nonexistent when you write the program, since if you don't have any idea what the target looks like, how can you output code for it? Do you mean physically existent?

I think I see the overall point though, namely that arch specific code would be a mess, with which I agree. But isn't this okay? I mean, if you really want to switch on some platform specific thing at compile time, then different behavior for different host platforms is exactly what you want.

To me, there's basically two uses of compile time execution: precomputation and codegen. If we look at the following snippet

  const std = @import("std");
  pub fn main() anyerror!void {
      std.debug.warn("{}\n", .{.{
          @sizeOf(*usize),
          comptime @sizeOf(*usize)
      }});
  }
we're looking at the size of a `usize`, which is pointer-sized, and we're taking it both with and without `comptime`. If I compile and run this on my system, it prints out 8 and 8, since I'm on a 64-bit system.

  /h/m/t/zig$ zig build run
  struct:5:21{ .0 = 8, .1 = 8 }
However, Zig does support cross compilation, and I can compile this for 32-bit mode, and run it, which then gives me 4 and 4.

  /h/m/t/zig$ zig build run -Dtarget=i386-linux-musl
  struct:5:21{ .0 = 4, .1 = 4 }
It's worth noting that the docs for `@sizeOf` says "This function returns the number of bytes it takes to store T in memory. The result is a target-specific compile time constant.".

> you a: need two different codegens

Won't you need `n` different codegens if you support cross compilation to `n` different targets anyways?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: