root/trunk/infrastructure/pyd/generators/ftype.py

Revision 38, 9.8 kB (checked in by KirkMcDonald, 2 years ago)

More opApply wrapping, docs

Line 
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 #
5 # ftype.py
6 # An evil hack in under 400 lines.
7 # Written by Daniel Keep
8 # Released to public domain—share and enjoy (just leave my name in it, pretty
9 # please).
10 #
11
12 # TODO:
13 # * Better error messages when you try to use a function with too many
14 #   arguments (it currently barfs with an unhelpful cascade of errors).
15
16 # This number controls the maximum number of arguments these templates will be
17 # able to process.  The higher you set this, the larger the output file
18 # becomes.
19 MAX_ARGS = 10
20
21 # This is the file the module will be output to.
22 OUT_FILE = "ftype.txt"
23
24 # This is the full name of the module.
25 MODULE_PATH = "pyd.ftype"
26
27 #
28 # Everything from here on isn't very interesting :)
29 #
30
31 # Redirect output to ftype.d
32 import sys
33 old_stdout = sys.stdout
34 sys.stdout = file(OUT_FILE, 'wt')
35
36 def typename(i):
37     if i == 0:
38         return "Tr"
39     else:
40         return "Ta%d" % i
41
42 def typenameinout(i):
43     if i == 0:
44         return "Tr"
45     else:
46         return "inout Ta%d" % i
47
48 def typeargs(n, omit_first=False):
49     if omit_first:
50         xs = range(1,n+1)
51     else:
52         xs = range(n+1)
53        
54     return ", ".join(typename(x) for x in xs)
55
56 def typeargsinout(n, omit_first=False):
57     if omit_first:
58         xs = range(1,n+1)
59     else:
60         xs = range(n+1)
61        
62     return ", ".join(typenameinout(x) for x in xs)
63
64 def typefptr(n):
65     return "%s function(%s)" % (typename(0), typeargs(n, True))
66
67 def typefninout(n):
68     return "%s function(%s)" % (typenameinout(0), typeargsinout(n, True))
69
70 def typedelegate(n):
71     return "%s delegate(%s)" % (typename(0), typeargs(n, True))
72
73 typefn = typefptr
74
75 #callable_types = ('F',typefptr), ('D',typedelegate)
76
77 #
78 # Module header
79 #
80
81 print """/**
82  * This module contains template for inferring the number of arguments,
83  * the return type, and argument types of an arbitrary function pointer.
84  *
85  * This module was automatically generated by ftype.py
86  *
87  * Written by Daniel Keep.
88  * Released to public domain—share and enjoy (just leave my name in it,
89  * pretty please).
90  */
91 module %s;
92 private:""" % MODULE_PATH
93
94 #
95 # Support templates
96 #
97
98 ##print """
99 ##/*
100 ## * This template tests whether a particular type is a function pointer.
101 ## *
102 ## * Borrowed from the traits library.
103 ## */
104 ##template
105 ##IsFunctionPtr(Tf)
106 ##{
107 ##    const bool IsFunctionPtr = is( typeof(*Tf) == function );
108 ##}"""
109 ##
110 ##print """
111 ##/*
112 ## * This template tests whether a particular type is a delegate.
113 ## *
114 ## * Borrowed from the traits library.
115 ## */
116 ##template
117 ##IsDelegate(Tf)
118 ##{
119 ##    const bool IsDelegate = is( Tf == delegate );
120 ##}"""
121
122 #
123 # NumberOfArgs(Tf)
124 #
125
126 print """
127 /* *** NumberOfArgs(Tf) *** */
128 """
129
130 for i in range(MAX_ARGS+1):
131     print "typedef uint Arglen%d = %d;" % (i, i)
132
133 for i in range(MAX_ARGS+1):
134     print ""
135     print "template"
136     print "ArglenT(%s)" % typeargs(i)
137     print "{"
138     print "    Arglen%d" % i
139     print "    ArglenT(%s fn) { assert(false); }" % typefn(i)
140     print "}"
141
142 print """
143 template
144 ArglenConvT(T)
145 {
146     const uint ArglenConvT = T.init;
147 }"""
148
149 print """
150 template
151 NumberOfArgsT(Tf)
152 {
153     private Tf fptr;
154     alias typeof(ArglenT(fptr)) type;
155 }"""
156
157 print """
158 template
159 NumberOfArgsSwitchT(Tf)
160 {
161     static if( is( typeof(*Tf) == function ) )
162         alias NumberOfArgsT!(Tf).type type;
163     else static if( is( Tf U == delegate ) )
164         alias NumberOfArgsSwitchT!(U*).type type;
165 }"""
166
167 print """
168 /**
169  * This template will attempt to determine the number of arguments the
170  * supplied function pointer or delegate type takes.  It supports a maximum of
171  * %d arguments.
172  *
173  * Example:
174  * ----------------------------------------
175  * void fnWithThreeArgs(byte a, short b, int c) {}
176  * const uint numArgs = NumberOfArgs!(typeof(&fnWithThreeArgs));
177  * ----------------------------------------
178  */
179 public
180 template
181 NumberOfArgs(Tf)
182 {
183     const uint NumberOfArgs = ArglenConvT!(NumberOfArgsSwitchT!(Tf).type);
184 }""" % MAX_ARGS
185
186 #
187 # NumberOfArgsInout
188 #
189 for i in range(MAX_ARGS+1):
190     print ""
191     print "template"
192     print "ArgleninoutT(%s)" % typeargs(i)
193     print "{"
194     print "    Arglen%d" % i
195     print "    ArgleninoutT(%s fn) { assert(false); }" % typefninout(i)
196     print "}"
197
198 print """
199 template
200 NumberOfArgsInoutT(Tf)
201 {
202     private Tf fptr;
203     alias typeof(ArgleninoutT(fptr)) type;
204 }"""
205
206 print """
207 template
208 NumberOfArgsSwitchInoutT(Tf)
209 {
210     static if( is( typeof(*Tf) == function ) )
211         alias NumberOfArgsInoutT!(Tf).type type;
212     else static if( is( Tf U == delegate ) )
213         alias NumberOfArgsSwitchInoutT!(U*).type type;
214 }"""
215
216 print """
217 public
218 template
219 NumberOfArgsInout(Tf)
220 {
221     const uint NumberOfArgsInout = ArglenConvT!(NumberOfArgsSwitchInoutT!(Tf).type);
222 }"""
223
224 #
225 # ReturnType(Tf)
226 #
227
228 ##print """
229 ##/* *** ReturnType(Tf) *** */"""
230 ##
231 ##for i in range(MAX_ARGS+1):
232 ##    for typecode,typefn in callable_types:
233 ##        print ""
234 ##        print "template"
235 ##        print "RetType%sT(%s)" % (typecode,typeargs(i))
236 ##        print "{"
237 ##        print "    %s" % typename(0)
238 ##        print "    RetType%sT(%s fn) { assert(false); }" % (typecode,typefn(i))
239 ##        print "}"
240
241 print """
242 template
243 ReturnTypeT(Tf)
244 {
245     private Tf fptr;
246     static if( is( typeof(*Tf) U == function ) )
247         alias U type;
248     else static if( is( Tf U == delegate ) )
249         alias ReturnType!(U*) type;
250     else
251         static assert(false, "ReturnType argument must be function pointer"
252                 " or delegate.");
253 }"""
254
255 print """
256 /**
257  * This template will attempt to discern the return type of the supplied
258  * function pointer or delegate type.  It supports callables with a maximum of
259  * %d arguments.
260  *
261  * Example:
262  * ----------------------------------------
263  * uint returnsANumber() { return 42; }
264  * alias ReturnType!(typeof(&returnsANumber)) RType; // RType == uint
265  * ----------------------------------------
266  */
267 public
268 template
269 ReturnType(Tf)
270 {
271     alias ReturnTypeT!(Tf).type ReturnType;
272 }""" % MAX_ARGS
273
274 #
275 # ArgType(Tf, n)
276 #
277
278 print """
279 /* *** ArgType(Tf, n) *** */"""
280
281 for n in range(1, MAX_ARGS+1):
282     for i in range(n, MAX_ARGS+1):
283         print ""
284         print "template"
285         print "Arg%dTypeT(%s)" % (n, typeargs(i))
286         print "{"
287         print "    %s Arg%dTypeT(%s fn) { assert(false); }" % (
288             typename(n), n, typefn(i))
289         print "}"
290
291 print """
292 template
293 ArgTypeT(Tf, uint n)
294 {
295     private Tf fptr;"""
296
297 for n in range(1, MAX_ARGS+1):
298     if n == 1:
299         print "    static if( n == %d )" % n
300     else:
301         print "    else static if( n == %d )" % n
302     print "        alias typeof(Arg%dTypeT(fptr)) type;" % n
303
304 print """    else
305         static assert(false,
306                 \"Maximum of %d arguments supported.\");
307 }""" % MAX_ARGS
308
309 print """
310 template
311 ArgTypeSwitchT(Tf, uint n)
312 {
313     static if( is( typeof(*Tf) == function ) )
314         alias ArgTypeT!(Tf, n).type type;
315     else static if( is( Tf U == delegate ) )
316         alias ArgTypeSwitchT!(U*, n).type type;
317     else
318         static assert(false, "ArgType argument must be a function pointer"
319                 " or a delegate.");
320 }"""
321
322 print """
323 /**
324  * This template will attempt to extract the type of the nth argument of the
325  * given function pointer or delegate type.  It supports callables with up to
326  * %d arguments.
327  *
328  * Example:
329  * ----------------------------------------
330  * void intShortBool(int a, short b, bool c) {}
331  * alias ArgType!(typeof(&intShortBool), 2) TArg2; // TArg2 == short
332  * ----------------------------------------
333  */
334 public
335 template
336 ArgType(Tf, uint n)
337 {
338     alias ArgTypeSwitchT!(Tf, n).type ArgType;
339 }""" % MAX_ARGS
340
341 #
342 # Unit tests
343 #
344
345 print """
346 /* *** Unit tests *** */"""
347
348 print """
349 unittest
350 {
351     alias int function()                                    fn_0args;
352     alias byte[] function(char)                             fn_1arg;
353     alias float[dchar] function(int, int[])                 fn_2args;
354     alias void function(int, float[char[]], ifloat[byte])   fn_3args;
355
356     alias int[] delegate()                                  dg_0args;
357     alias real delegate(uint[])                             dg_1arg;
358     alias void delegate(char[][char[]], bool[short])        dg_2args;
359     alias dchar[wchar] delegate(byte, short, int)           dg_3args;
360
361     // ** Test NumberOfArgs(Tf) ** //
362
363     static assert( NumberOfArgs!(fn_0args) == 0 );
364     static assert( NumberOfArgs!(fn_1arg) == 1 );
365     static assert( NumberOfArgs!(fn_2args) == 2 );
366     static assert( NumberOfArgs!(fn_3args) == 3 );
367     static assert( NumberOfArgs!(dg_0args) == 0 );
368     static assert( NumberOfArgs!(dg_1arg) == 1 );
369     static assert( NumberOfArgs!(dg_2args) == 2 );
370     static assert( NumberOfArgs!(dg_3args) == 3 );
371
372     // ** Test ReturnType(Tf) ** //
373
374     static assert( is( ReturnType!(fn_0args) == int ) );
375     static assert( is( ReturnType!(fn_1arg) == byte[] ) );
376     static assert( is( ReturnType!(fn_2args) == float[dchar] ) );
377     static assert( is( ReturnType!(fn_3args) == void ) );
378     static assert( is( ReturnType!(dg_0args) == int[] ) );
379     static assert( is( ReturnType!(dg_1arg) == real ) );
380     static assert( is( ReturnType!(dg_2args) == void ) );
381     static assert( is( ReturnType!(dg_3args) == dchar[wchar] ) );
382
383     // ** Test ArgType(Tf, n) ** //
384
385     static assert( is( ArgType!(fn_1arg, 1) == char ) );
386     static assert( is( ArgType!(fn_2args, 2) == int[] ) );
387     static assert( is( ArgType!(fn_3args, 3) == ifloat[byte] ) );
388     static assert( is( ArgType!(dg_2args, 1) == char[][char[]] ) );
389     static assert( is( ArgType!(dg_3args, 1) == byte ) );
390     static assert( is( ArgType!(dg_3args, 2) == short ) );
391
392     pragma(msg, "ftype: passed static unit tests.");
393 }
394 """
395
396 # Restore stdout
397 sys.stdout = old_stdout
Note: See TracBrowser for help on using the browser.