How to conditionally include/exclude functions from a namespace without usingnamespace?

My project let Javascript developrtd use Zig code in their projects. Say you have the file “foobar.zig”:

pub fn foo() !void {
    // do foo
}

pub fn bar() !void {
   // do bar
}

You can import that into Javascript with my toolkit:

import { foo, bar } from '../zig/foobar.zig';

foo();
bar();

The scan determines what’s available. Every decl is going to be touched during this scan. If a decl points to a @compileError() then it killed everything. If it points to a void (or undefined) then there would just be a pointless declaration that resolves to a JavaScript undefined. An attempt to call it as a function would bring up a not-particularly helpful error message: “Undefined in not a function”.

If I can identify the reason why I’m getting an unusable result, then I can throw an error on the JavaScript side with a message that better describes what’s going on.

A zero-byte struct containing no usable information at runtime can actually be quite powerful at comptime. We should take advantage of it.

If it were possible to construct a reified Type which had declarations, this would of course be a pleasant task.

How about something like this?

pub const foo = conditionalInclude(.single_threaded, blah);

In the reflection code, check if the @TypeOf(foo) is some special sentinel that means “disabled”. This can contain your error message for the JS side.

2 Likes

Another thought - you could bundle all the conditional decls into a namespace (a struct, say), which will always exist but just have a different definition expression depending on the condition.

const conditionalMethods = if (condition) struct {…} else struct {…}

Give it a special marker and let your reflection code recurse through decls that have this marker.

The downside here is that you have to change your surrounding code to call the conditional functions through conditionalMethods. Although, maybe that’s actually a good thing as it localizes the fact that it’s conditional.
The upside is that it seems very explicit, the only ‘magic’ happens in your reflection code when you recurse through the special marker.