Skip to content

Commit 4ca0e65

Browse files
committed
macro magic to DRY up externs
1 parent 95431fd commit 4ca0e65

File tree

1 file changed

+104
-109
lines changed

1 file changed

+104
-109
lines changed

src/cli/modules.c

Lines changed: 104 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -9,45 +9,6 @@
99
#include "scheduler.wren.inc"
1010
#include "timer.wren.inc"
1111

12-
extern void directoryList(WrenVM* vm);
13-
extern void fileAllocate(WrenVM* vm);
14-
extern void fileFinalize(void* data);
15-
extern void fileDelete(WrenVM* vm);
16-
extern void fileOpen(WrenVM* vm);
17-
extern void fileSizePath(WrenVM* vm);
18-
extern void fileClose(WrenVM* vm);
19-
extern void fileDescriptor(WrenVM* vm);
20-
extern void fileReadBytes(WrenVM* vm);
21-
extern void fileRealPath(WrenVM* vm);
22-
extern void fileSize(WrenVM* vm);
23-
extern void fileStat(WrenVM* vm);
24-
extern void fileWriteBytes(WrenVM* vm);
25-
extern void platformIsPosix(WrenVM* vm);
26-
extern void platformName(WrenVM* vm);
27-
extern void processAllArguments(WrenVM* vm);
28-
extern void processVersion(WrenVM* vm);
29-
extern void processCwd(WrenVM* vm);
30-
extern void statPath(WrenVM* vm);
31-
extern void statBlockCount(WrenVM* vm);
32-
extern void statBlockSize(WrenVM* vm);
33-
extern void statDevice(WrenVM* vm);
34-
extern void statGroup(WrenVM* vm);
35-
extern void statInode(WrenVM* vm);
36-
extern void statLinkCount(WrenVM* vm);
37-
extern void statMode(WrenVM* vm);
38-
extern void statSize(WrenVM* vm);
39-
extern void statSpecialDevice(WrenVM* vm);
40-
extern void statUser(WrenVM* vm);
41-
extern void statIsDirectory(WrenVM* vm);
42-
extern void statIsFile(WrenVM* vm);
43-
extern void stdinIsRaw(WrenVM* vm);
44-
extern void stdinIsRawSet(WrenVM* vm);
45-
extern void stdinIsTerminal(WrenVM* vm);
46-
extern void stdinReadStart(WrenVM* vm);
47-
extern void stdinReadStop(WrenVM* vm);
48-
extern void stdoutFlush(WrenVM* vm);
49-
extern void schedulerCaptureMethods(WrenVM* vm);
50-
extern void timerStartTimer(WrenVM* vm);
5112

5213
// The maximum number of foreign methods a single class defines. Ideally, we
5314
// would use variable-length arrays for each class in the table below, but
@@ -96,12 +57,113 @@ typedef struct
9657
ClassRegistry classes[MAX_CLASSES_PER_MODULE];
9758
} ModuleRegistry;
9859

60+
#define METHOD(signature, fn) extern void fn (WrenVM* vm);;
61+
#define STATIC_METHOD(signature, fn) extern void fn (WrenVM* vm);;
62+
#define FINALIZER(fn) extern void fn (WrenVM* vm);;
63+
#define SENTINEL_METHOD
64+
#define SENTINEL_CLASS
65+
#define MODULE(name)
66+
#define END_MODULE
67+
#define CLASS(name)
68+
#define END_CLASS
69+
70+
// MODULES, CLASSES, METHODS
71+
//
72+
// all modules as well as any foreign classes or methods must be included in
73+
// this list to connect them to their counterpart C functions
74+
//
75+
// This macro is used to construct both the `ModuleRegistry` as well as the full
76+
// list of externs so that they do not need to be maintained by hand.
77+
#define REGISTRY MODULE(io) \
78+
CLASS(Directory) \
79+
STATIC_METHOD("list_(_,_)", directoryList) \
80+
END_CLASS \
81+
CLASS(File) \
82+
STATIC_METHOD("<allocate>", fileAllocate) \
83+
FINALIZER(fileFinalize) \
84+
STATIC_METHOD("delete_(_,_)", fileDelete) \
85+
STATIC_METHOD("open_(_,_,_)", fileOpen) \
86+
STATIC_METHOD("realPath_(_,_)", fileRealPath) \
87+
STATIC_METHOD("sizePath_(_,_)", fileSizePath) \
88+
METHOD("close_(_)", fileClose) \
89+
METHOD("descriptor", fileDescriptor) \
90+
METHOD("readBytes_(_,_,_)", fileReadBytes) \
91+
METHOD("size_(_)", fileSize) \
92+
METHOD("stat_(_)", fileStat) \
93+
METHOD("writeBytes_(_,_,_)", fileWriteBytes) \
94+
END_CLASS \
95+
CLASS(Stat) \
96+
STATIC_METHOD("path_(_,_)", statPath) \
97+
METHOD("blockCount", statBlockCount) \
98+
METHOD("blockSize", statBlockSize) \
99+
METHOD("device", statDevice) \
100+
METHOD("group", statGroup) \
101+
METHOD("inode", statInode) \
102+
METHOD("linkCount", statLinkCount) \
103+
METHOD("mode", statMode) \
104+
METHOD("size", statSize) \
105+
METHOD("specialDevice", statSpecialDevice) \
106+
METHOD("user", statUser) \
107+
METHOD("isDirectory", statIsDirectory) \
108+
METHOD("isFile", statIsFile) \
109+
END_CLASS \
110+
CLASS(Stdin) \
111+
STATIC_METHOD("isRaw", stdinIsRaw) \
112+
STATIC_METHOD("isRaw=(_)", stdinIsRawSet) \
113+
STATIC_METHOD("isTerminal", stdinIsTerminal) \
114+
STATIC_METHOD("readStart_()", stdinReadStart) \
115+
STATIC_METHOD("readStop_()", stdinReadStop) \
116+
END_CLASS \
117+
CLASS(Stdout) \
118+
STATIC_METHOD("flush()", stdoutFlush) \
119+
END_CLASS \
120+
END_MODULE \
121+
MODULE(os) \
122+
CLASS(Platform) \
123+
STATIC_METHOD("isPosix", platformIsPosix) \
124+
STATIC_METHOD("name", platformName) \
125+
END_CLASS \
126+
CLASS(Process) \
127+
STATIC_METHOD("allArguments", processAllArguments) \
128+
STATIC_METHOD("version", processVersion) \
129+
STATIC_METHOD("cwd", processCwd) \
130+
END_CLASS \
131+
END_MODULE \
132+
MODULE(repl) \
133+
END_MODULE \
134+
MODULE(scheduler) \
135+
CLASS(Scheduler) \
136+
STATIC_METHOD("captureMethods_()", schedulerCaptureMethods) \
137+
END_CLASS \
138+
END_MODULE \
139+
MODULE(timer) \
140+
CLASS(Timer) \
141+
STATIC_METHOD("startTimer_(_,_)", timerStartTimer) \
142+
END_CLASS \
143+
END_MODULE
144+
145+
// this first use of REGISTRY builds out the list of externs
146+
// extern void directoryList(WrenVM* vm);
147+
// extern void fileAllocate(WrenVM* vm);
148+
// ...
149+
REGISTRY
150+
151+
#undef SENTINEL_METHOD
152+
#undef SENTINEL_CLASS
153+
#undef MODULE
154+
#undef END_MODULE
155+
#undef CLASS
156+
#undef END_CLASS
157+
#undef METHOD
158+
#undef STATIC_METHOD
159+
#undef FINALIZER
160+
99161
// To locate foreign classes and modules, we build a big directory for them in
100162
// static data. The nested collection initializer syntax gets pretty noisy, so
101163
// define a couple of macros to make it easier.
102164
#define SENTINEL_METHOD { false, NULL, NULL }
103165
#define SENTINEL_CLASS { NULL, { SENTINEL_METHOD } }
104-
#define SENTINEL_MODULE {NULL, NULL, { SENTINEL_CLASS } }
166+
#define END_REGISTRY
105167

106168
#define MODULE(name) { #name, &name##ModuleSource, {
107169
#define END_MODULE SENTINEL_CLASS } },
@@ -116,75 +178,8 @@ typedef struct
116178
// The array of built-in modules.
117179
static ModuleRegistry modules[] =
118180
{
119-
MODULE(io)
120-
CLASS(Directory)
121-
STATIC_METHOD("list_(_,_)", directoryList)
122-
END_CLASS
123-
CLASS(File)
124-
STATIC_METHOD("<allocate>", fileAllocate)
125-
FINALIZER(fileFinalize)
126-
STATIC_METHOD("delete_(_,_)", fileDelete)
127-
STATIC_METHOD("open_(_,_,_)", fileOpen)
128-
STATIC_METHOD("realPath_(_,_)", fileRealPath)
129-
STATIC_METHOD("sizePath_(_,_)", fileSizePath)
130-
METHOD("close_(_)", fileClose)
131-
METHOD("descriptor", fileDescriptor)
132-
METHOD("readBytes_(_,_,_)", fileReadBytes)
133-
METHOD("size_(_)", fileSize)
134-
METHOD("stat_(_)", fileStat)
135-
METHOD("writeBytes_(_,_,_)", fileWriteBytes)
136-
END_CLASS
137-
CLASS(Stat)
138-
STATIC_METHOD("path_(_,_)", statPath)
139-
METHOD("blockCount", statBlockCount)
140-
METHOD("blockSize", statBlockSize)
141-
METHOD("device", statDevice)
142-
METHOD("group", statGroup)
143-
METHOD("inode", statInode)
144-
METHOD("linkCount", statLinkCount)
145-
METHOD("mode", statMode)
146-
METHOD("size", statSize)
147-
METHOD("specialDevice", statSpecialDevice)
148-
METHOD("user", statUser)
149-
METHOD("isDirectory", statIsDirectory)
150-
METHOD("isFile", statIsFile)
151-
END_CLASS
152-
CLASS(Stdin)
153-
STATIC_METHOD("isRaw", stdinIsRaw)
154-
STATIC_METHOD("isRaw=(_)", stdinIsRawSet)
155-
STATIC_METHOD("isTerminal", stdinIsTerminal)
156-
STATIC_METHOD("readStart_()", stdinReadStart)
157-
STATIC_METHOD("readStop_()", stdinReadStop)
158-
END_CLASS
159-
CLASS(Stdout)
160-
STATIC_METHOD("flush()", stdoutFlush)
161-
END_CLASS
162-
END_MODULE
163-
MODULE(os)
164-
CLASS(Platform)
165-
STATIC_METHOD("isPosix", platformIsPosix)
166-
STATIC_METHOD("name", platformName)
167-
END_CLASS
168-
CLASS(Process)
169-
STATIC_METHOD("allArguments", processAllArguments)
170-
STATIC_METHOD("version", processVersion)
171-
STATIC_METHOD("cwd", processCwd)
172-
END_CLASS
173-
END_MODULE
174-
MODULE(repl)
175-
END_MODULE
176-
MODULE(scheduler)
177-
CLASS(Scheduler)
178-
STATIC_METHOD("captureMethods_()", schedulerCaptureMethods)
179-
END_CLASS
180-
END_MODULE
181-
MODULE(timer)
182-
CLASS(Timer)
183-
STATIC_METHOD("startTimer_(_,_)", timerStartTimer)
184-
END_CLASS
185-
END_MODULE
186-
187-
SENTINEL_MODULE
181+
REGISTRY
182+
END_REGISTRY
188183
};
189184

190185
#undef SENTINEL_METHOD

0 commit comments

Comments
 (0)