Skip to content
File

Blob: src/workerd/jsg/macro-meta.h

cpp114 lines
1// Copyright (c) 2017-2022 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4 
5#pragma once
6// INTERNAL IMPLEMENTATION FILE
7//
8// Some macro metaprogramming helpers.
9 
10// =======================================================================================
11// TODO(cleanup): Move these macros to libkj.
12 
13#define JSG_STRING_LITERAL_(...) #__VA_ARGS__
14#define JSG_STRING_LITERAL(...) JSG_STRING_LITERAL_(__VA_ARGS__)
15// JSG_STRING_LITERAL(foo, bar) expands to the string literal: "foo, bar".
16//
17// This is the standard two-step "stringify after macro expansion" idiom: arguments are
18// macro-expanded first, then stringified. Useful when callers pass identifiers that are themselves
19// macros and you want to capture the expanded value (e.g. `JSG_STRING_LITERAL(__LINE__)` ->
20// `"123"`).
21//
22// Do NOT use this to stringify user-supplied source-code blocks -- the implicit expansion will
23// silently corrupt identifiers that happen to collide with platform header macros. On Darwin, for
24// example, `<stdio.h>` defines `stdin`/`stdout`/`stderr` as `__stdinp`/`__stdoutp`/`__stderrp`, so
25// `JSG_STRING_LITERAL({ stdin: 1 })` produces `"{ __stdinp: 1 }"` rather than the literal text.
26// For source-code blocks, stringify directly with `#__VA_ARGS__` at the outermost macro that
27// captures the user's tokens (see `JSG_TS_OVERRIDE` in jsg.h for an example).
28 
29#define JSG_EXPAND(...) __VA_ARGS__
30// Identity macro. Often useful in macro hacking.
31 
32#define JSG_IF_NONEMPTY_( \
33 dummy, part1, part2, part3, part4, part5, part6, part7, part8, result, ...) \
34 JSG_EXPAND result
35#define JSG_IF_NONEMPTY_2_(...) dummy, ##__VA_ARGS__
36#define JSG_IF_NONEMPTY_3_(...) JSG_IF_NONEMPTY_(__VA_ARGS__)
37#define JSG_IF_NONEMPTY(arg, ...) \
38 JSG_IF_NONEMPTY_3_(JSG_IF_NONEMPTY_2_(arg), (__VA_ARGS__), (__VA_ARGS__), (__VA_ARGS__), \
39 (__VA_ARGS__), (__VA_ARGS__), (__VA_ARGS__), (__VA_ARGS__), (__VA_ARGS__), ())
40 
41#define JSG_CAT(a, b) a##b
42// Paste two preprocessor tokens together. Useful in macro hacking.
43 
44// If the first argument is empty, expands to nothing.
45//
46// If the first argument is not empty, expands to the remaining arguments.
47//
48// So:
49// JSG_IF_NONEMPTY(, foo, bar) ->
50// JSG_IF_NONEMPTY(x, foo, bar) -> foo, bar
51//
52// (We support multiple "arguments" because often the output needs to contain commas, e.g. because
53// it's a template type and the preprocessor doesn't recognize <...> as a grouping.)
54 
55#define JSG_FOR_EACH_(op, param, A1, A2, A3, A4, A5, A6, A7, A8, B1, B2, B3, B4, B5, B6, B7, B8, \
56 C1, C2, C3, C4, C5, C6, C7, C8, D1, D2, D3, D4, D5, D6, D7, D8, E1, E2, E3, E4, E5, E6, E7, \
57 E8, F1, F2, F3, F4, F5, F6, F7, F8, sentinel, ...) \
58 JSG_IF_NONEMPTY(A1, op(param, A1)) \
59 JSG_IF_NONEMPTY(A2, , op(param, A2)) \
60 JSG_IF_NONEMPTY(A3, , op(param, A3)) \
61 JSG_IF_NONEMPTY(A4, , op(param, A4)) \
62 JSG_IF_NONEMPTY(A5, , op(param, A5)) \
63 JSG_IF_NONEMPTY(A6, , op(param, A6)) \
64 JSG_IF_NONEMPTY(A7, , op(param, A7)) \
65 JSG_IF_NONEMPTY(A8, , op(param, A8)) \
66 JSG_IF_NONEMPTY(B1, , op(param, B1)) \
67 JSG_IF_NONEMPTY(B2, , op(param, B2)) \
68 JSG_IF_NONEMPTY(B3, , op(param, B3)) \
69 JSG_IF_NONEMPTY(B4, , op(param, B4)) \
70 JSG_IF_NONEMPTY(B5, , op(param, B5)) \
71 JSG_IF_NONEMPTY(B6, , op(param, B6)) \
72 JSG_IF_NONEMPTY(B7, , op(param, B7)) \
73 JSG_IF_NONEMPTY(B8, , op(param, B8)) \
74 JSG_IF_NONEMPTY(C1, , op(param, C1)) \
75 JSG_IF_NONEMPTY(C2, , op(param, C2)) \
76 JSG_IF_NONEMPTY(C3, , op(param, C3)) \
77 JSG_IF_NONEMPTY(C4, , op(param, C4)) \
78 JSG_IF_NONEMPTY(C5, , op(param, C5)) \
79 JSG_IF_NONEMPTY(C6, , op(param, C6)) \
80 JSG_IF_NONEMPTY(C7, , op(param, C7)) \
81 JSG_IF_NONEMPTY(C8, , op(param, C8)) \
82 JSG_IF_NONEMPTY(D1, , op(param, D1)) \
83 JSG_IF_NONEMPTY(D2, , op(param, D2)) \
84 JSG_IF_NONEMPTY(D3, , op(param, D3)) \
85 JSG_IF_NONEMPTY(D4, , op(param, D4)) \
86 JSG_IF_NONEMPTY(D5, , op(param, D5)) \
87 JSG_IF_NONEMPTY(D6, , op(param, D6)) \
88 JSG_IF_NONEMPTY(D7, , op(param, D7)) \
89 JSG_IF_NONEMPTY(D8, , op(param, D8)) \
90 JSG_IF_NONEMPTY(E1, , op(param, E1)) \
91 JSG_IF_NONEMPTY(E2, , op(param, E2)) \
92 JSG_IF_NONEMPTY(E3, , op(param, E3)) \
93 JSG_IF_NONEMPTY(E4, , op(param, E4)) \
94 JSG_IF_NONEMPTY(E5, , op(param, E5)) \
95 JSG_IF_NONEMPTY(E6, , op(param, E6)) \
96 JSG_IF_NONEMPTY(E7, , op(param, E7)) \
97 JSG_IF_NONEMPTY(E8, , op(param, E8)) \
98 JSG_IF_NONEMPTY(F1, , op(param, F1)) \
99 JSG_IF_NONEMPTY(F2, , op(param, F2)) \
100 JSG_IF_NONEMPTY(F3, , op(param, F3)) \
101 JSG_IF_NONEMPTY(F4, , op(param, F4)) \
102 JSG_IF_NONEMPTY(F5, , op(param, F5)) \
103 JSG_IF_NONEMPTY(F6, , op(param, F6)) \
104 JSG_IF_NONEMPTY(F7, , op(param, F7)) \
105 JSG_IF_NONEMPTY(F8, , op(param, F8)) \
106 JSG_IF_NONEMPTY(sentinel, error_JSG_FOR_EACH_only_supports_48_parameters)
107 
108#define JSG_FOR_EACH(op, param, ...) \
109 JSG_FOR_EACH_(op, param, ##__VA_ARGS__, , , , , , , , , , , , , , , , , , , , , , , , , , , , , \
110 , , , , , , , , , , , , , , , , , , , , )
111// JSG_FOR_EACH(op, param, A, B, C, ...) expands to: op(param, A), op(param, B), op(param, C) ...
112//
113// Currently only supports up to 48 params.